blob: 8fab8dbe80bb33cd09f8d31fead747095cce3288 [file] [log] [blame]
Linus Torvalds0fcfd162005-04-18 13:04:43 -07001/*
2 * GIT - The information manager from hell
3 *
4 * Copyright (C) Linus Torvalds, 2005
5 *
Martin Ågrene5afd442020-12-31 12:56:21 +01006 * This handles basic git object files - packing, unpacking,
Linus Torvalds0fcfd162005-04-18 13:04:43 -07007 * creation etc.
8 */
Elijah Newren36bf1952023-02-24 00:09:24 +00009#include "git-compat-util.h"
10#include "alloc.h"
Brandon Williamsb2141fc2017-06-14 11:07:36 -070011#include "config.h"
Elijah Newren41771fa2023-02-24 00:09:27 +000012#include "hex.h"
Michael Haggerty6eac50d2012-11-05 09:41:22 +010013#include "string-list.h"
Michael Haggerty697cc8e2014-10-01 12:28:42 +020014#include "lockfile.h"
Junio C Hamano1f688552005-06-27 03:35:33 -070015#include "delta.h"
Linus Torvaldsa733cb62005-06-28 14:21:02 -070016#include "pack.h"
Peter Eriksen8e440252006-04-02 14:44:09 +020017#include "blob.h"
18#include "commit.h"
Junio C Hamano4dd1fbc2011-05-08 01:47:35 -070019#include "run-command.h"
Peter Eriksen8e440252006-04-02 14:44:09 +020020#include "tag.h"
21#include "tree.h"
Nguyễn Thái Ngọc Duyc879daa2011-02-05 17:52:21 +070022#include "tree-walk.h"
Linus Torvaldsf35a6d32007-04-09 21:20:29 -070023#include "refs.h"
Nicolas Pitre70f5d5d2008-02-28 00:25:19 -050024#include "pack-revindex.h"
Martin Ågrenbc626922020-12-31 12:56:23 +010025#include "hash-lookup.h"
Junio C Hamano568508e2011-10-28 14:48:40 -070026#include "bulk-checkin.h"
Stefan Beller031dc922018-03-23 18:20:57 +010027#include "repository.h"
Stefan Beller47f351e2018-04-11 17:21:06 -070028#include "replace-object.h"
Nguyễn Thái Ngọc Duy090ea122012-03-07 17:54:18 +070029#include "streaming.h"
Nguyễn Thái Ngọc Duy543c5ca2013-02-15 19:07:10 +070030#include "dir.h"
Jeff King12d95ef2016-08-22 17:59:42 -040031#include "list.h"
René Scharfec4c6eff2016-09-13 19:54:42 +020032#include "mergesort.h"
Jeff Kingcf3c6352016-12-12 14:52:22 -050033#include "quote.h"
Jonathan Tan4f39cd82017-08-18 15:20:16 -070034#include "packfile.h"
Stefan Beller90c62152018-03-23 18:20:55 +010035#include "object-store.h"
Christian Couderb14ed5a2019-06-25 15:40:31 +020036#include "promisor-remote.h"
Jonathan Tana35e03d2021-08-16 14:09:51 -070037#include "submodule.h"
Jeff King69bbbe42023-01-18 15:44:12 -050038#include "fsck.h"
Pavel Roskine05db0f2007-01-09 23:07:11 -050039
brian m. carlson1af64f72018-03-12 02:27:55 +000040/* The maximum size for an object header. */
41#define MAX_HEADER_LEN 32
42
brian m. carlsone1ccd7e2018-05-02 00:26:07 +000043
44#define EMPTY_TREE_SHA1_BIN_LITERAL \
45 "\x4b\x82\x5d\xc6\x42\xcb\x6e\xb9\xa0\x60" \
46 "\xe5\x4b\xf8\xd6\x92\x88\xfb\xee\x49\x04"
brian m. carlson13eeedb2018-11-14 04:09:36 +000047#define EMPTY_TREE_SHA256_BIN_LITERAL \
48 "\x6e\xf1\x9b\x41\x22\x5c\x53\x69\xf1\xc1" \
49 "\x04\xd4\x5d\x8d\x85\xef\xa9\xb0\x57\xb5" \
50 "\x3b\x14\xb4\xb9\xb9\x39\xdd\x74\xde\xcc" \
51 "\x53\x21"
brian m. carlsone1ccd7e2018-05-02 00:26:07 +000052
53#define EMPTY_BLOB_SHA1_BIN_LITERAL \
54 "\xe6\x9d\xe2\x9b\xb2\xd1\xd6\x43\x4b\x8b" \
55 "\x29\xae\x77\x5a\xd8\xc2\xe4\x8c\x53\x91"
brian m. carlson13eeedb2018-11-14 04:09:36 +000056#define EMPTY_BLOB_SHA256_BIN_LITERAL \
57 "\x47\x3a\x0f\x4c\x3b\xe8\xa9\x36\x81\xa2" \
58 "\x67\xe3\xb1\xe9\xa7\xdc\xda\x11\x85\x43" \
59 "\x6f\xe1\x41\xf7\x74\x91\x20\xa3\x03\x72" \
60 "\x18\x13"
brian m. carlsone1ccd7e2018-05-02 00:26:07 +000061
brian m. carlsone1ccd7e2018-05-02 00:26:07 +000062static const struct object_id empty_tree_oid = {
brian m. carlson5a6dce72021-04-26 01:02:55 +000063 .hash = EMPTY_TREE_SHA1_BIN_LITERAL,
64 .algo = GIT_HASH_SHA1,
Jacob Keller8576fde2016-08-31 16:27:18 -070065};
brian m. carlsone1ccd7e2018-05-02 00:26:07 +000066static const struct object_id empty_blob_oid = {
brian m. carlson5a6dce72021-04-26 01:02:55 +000067 .hash = EMPTY_BLOB_SHA1_BIN_LITERAL,
68 .algo = GIT_HASH_SHA1,
Jacob Keller8576fde2016-08-31 16:27:18 -070069};
brian m. carlson14228442021-04-26 01:02:56 +000070static const struct object_id null_oid_sha1 = {
71 .hash = {0},
72 .algo = GIT_HASH_SHA1,
73};
brian m. carlson13eeedb2018-11-14 04:09:36 +000074static const struct object_id empty_tree_oid_sha256 = {
brian m. carlson5a6dce72021-04-26 01:02:55 +000075 .hash = EMPTY_TREE_SHA256_BIN_LITERAL,
76 .algo = GIT_HASH_SHA256,
brian m. carlson13eeedb2018-11-14 04:09:36 +000077};
78static const struct object_id empty_blob_oid_sha256 = {
brian m. carlson5a6dce72021-04-26 01:02:55 +000079 .hash = EMPTY_BLOB_SHA256_BIN_LITERAL,
80 .algo = GIT_HASH_SHA256,
brian m. carlson13eeedb2018-11-14 04:09:36 +000081};
brian m. carlson14228442021-04-26 01:02:56 +000082static const struct object_id null_oid_sha256 = {
83 .hash = {0},
84 .algo = GIT_HASH_SHA256,
85};
Junio C Hamano88cd6212005-09-30 14:02:47 -070086
brian m. carlsonac73ced2018-02-01 02:18:38 +000087static void git_hash_sha1_init(git_hash_ctx *ctx)
brian m. carlsonf50e7662017-11-12 21:28:52 +000088{
brian m. carlsonac73ced2018-02-01 02:18:38 +000089 git_SHA1_Init(&ctx->sha1);
brian m. carlsonf50e7662017-11-12 21:28:52 +000090}
91
brian m. carlson768e30e2020-02-22 20:17:27 +000092static void git_hash_sha1_clone(git_hash_ctx *dst, const git_hash_ctx *src)
93{
94 git_SHA1_Clone(&dst->sha1, &src->sha1);
95}
96
brian m. carlsonac73ced2018-02-01 02:18:38 +000097static void git_hash_sha1_update(git_hash_ctx *ctx, const void *data, size_t len)
brian m. carlsonf50e7662017-11-12 21:28:52 +000098{
brian m. carlsonac73ced2018-02-01 02:18:38 +000099 git_SHA1_Update(&ctx->sha1, data, len);
brian m. carlsonf50e7662017-11-12 21:28:52 +0000100}
101
brian m. carlsonac73ced2018-02-01 02:18:38 +0000102static void git_hash_sha1_final(unsigned char *hash, git_hash_ctx *ctx)
brian m. carlsonf50e7662017-11-12 21:28:52 +0000103{
brian m. carlsonac73ced2018-02-01 02:18:38 +0000104 git_SHA1_Final(hash, &ctx->sha1);
brian m. carlsonf50e7662017-11-12 21:28:52 +0000105}
106
brian m. carlsonab795f02021-04-26 01:02:52 +0000107static void git_hash_sha1_final_oid(struct object_id *oid, git_hash_ctx *ctx)
108{
109 git_SHA1_Final(oid->hash, &ctx->sha1);
110 memset(oid->hash + GIT_SHA1_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA1_RAWSZ);
brian m. carlson5a6dce72021-04-26 01:02:55 +0000111 oid->algo = GIT_HASH_SHA1;
brian m. carlsonab795f02021-04-26 01:02:52 +0000112}
113
brian m. carlson13eeedb2018-11-14 04:09:36 +0000114
115static void git_hash_sha256_init(git_hash_ctx *ctx)
116{
117 git_SHA256_Init(&ctx->sha256);
118}
119
brian m. carlson768e30e2020-02-22 20:17:27 +0000120static void git_hash_sha256_clone(git_hash_ctx *dst, const git_hash_ctx *src)
121{
122 git_SHA256_Clone(&dst->sha256, &src->sha256);
123}
124
brian m. carlson13eeedb2018-11-14 04:09:36 +0000125static void git_hash_sha256_update(git_hash_ctx *ctx, const void *data, size_t len)
126{
127 git_SHA256_Update(&ctx->sha256, data, len);
128}
129
130static void git_hash_sha256_final(unsigned char *hash, git_hash_ctx *ctx)
131{
132 git_SHA256_Final(hash, &ctx->sha256);
133}
134
brian m. carlsonab795f02021-04-26 01:02:52 +0000135static void git_hash_sha256_final_oid(struct object_id *oid, git_hash_ctx *ctx)
136{
137 git_SHA256_Final(oid->hash, &ctx->sha256);
138 /*
139 * This currently does nothing, so the compiler should optimize it out,
140 * but keep it in case we extend the hash size again.
141 */
142 memset(oid->hash + GIT_SHA256_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA256_RAWSZ);
brian m. carlson5a6dce72021-04-26 01:02:55 +0000143 oid->algo = GIT_HASH_SHA256;
brian m. carlsonab795f02021-04-26 01:02:52 +0000144}
145
Jeff King9eb6cda2022-10-17 21:05:28 -0400146static void git_hash_unknown_init(git_hash_ctx *ctx UNUSED)
brian m. carlsonf50e7662017-11-12 21:28:52 +0000147{
Nguyễn Thái Ngọc Duy1a07e592018-07-21 09:49:19 +0200148 BUG("trying to init unknown hash");
brian m. carlsonf50e7662017-11-12 21:28:52 +0000149}
150
Jeff King9eb6cda2022-10-17 21:05:28 -0400151static void git_hash_unknown_clone(git_hash_ctx *dst UNUSED,
152 const git_hash_ctx *src UNUSED)
brian m. carlson768e30e2020-02-22 20:17:27 +0000153{
154 BUG("trying to clone unknown hash");
155}
156
Jeff King9eb6cda2022-10-17 21:05:28 -0400157static void git_hash_unknown_update(git_hash_ctx *ctx UNUSED,
158 const void *data UNUSED,
159 size_t len UNUSED)
brian m. carlsonf50e7662017-11-12 21:28:52 +0000160{
Nguyễn Thái Ngọc Duy1a07e592018-07-21 09:49:19 +0200161 BUG("trying to update unknown hash");
brian m. carlsonf50e7662017-11-12 21:28:52 +0000162}
163
Jeff King9eb6cda2022-10-17 21:05:28 -0400164static void git_hash_unknown_final(unsigned char *hash UNUSED,
165 git_hash_ctx *ctx UNUSED)
brian m. carlsonf50e7662017-11-12 21:28:52 +0000166{
Nguyễn Thái Ngọc Duy1a07e592018-07-21 09:49:19 +0200167 BUG("trying to finalize unknown hash");
brian m. carlsonf50e7662017-11-12 21:28:52 +0000168}
169
Jeff King9eb6cda2022-10-17 21:05:28 -0400170static void git_hash_unknown_final_oid(struct object_id *oid UNUSED,
171 git_hash_ctx *ctx UNUSED)
brian m. carlsonab795f02021-04-26 01:02:52 +0000172{
173 BUG("trying to finalize unknown hash");
174}
175
brian m. carlsonf50e7662017-11-12 21:28:52 +0000176const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = {
177 {
Ævar Arnfjörð Bjarmason0cb98722022-02-24 10:33:01 +0100178 .name = NULL,
179 .format_id = 0x00000000,
180 .rawsz = 0,
181 .hexsz = 0,
182 .blksz = 0,
183 .init_fn = git_hash_unknown_init,
184 .clone_fn = git_hash_unknown_clone,
185 .update_fn = git_hash_unknown_update,
186 .final_fn = git_hash_unknown_final,
187 .final_oid_fn = git_hash_unknown_final_oid,
188 .empty_tree = NULL,
189 .empty_blob = NULL,
190 .null_oid = NULL,
brian m. carlsonf50e7662017-11-12 21:28:52 +0000191 },
192 {
Ævar Arnfjörð Bjarmason0cb98722022-02-24 10:33:01 +0100193 .name = "sha1",
194 .format_id = GIT_SHA1_FORMAT_ID,
195 .rawsz = GIT_SHA1_RAWSZ,
196 .hexsz = GIT_SHA1_HEXSZ,
197 .blksz = GIT_SHA1_BLKSZ,
198 .init_fn = git_hash_sha1_init,
199 .clone_fn = git_hash_sha1_clone,
200 .update_fn = git_hash_sha1_update,
201 .final_fn = git_hash_sha1_final,
202 .final_oid_fn = git_hash_sha1_final_oid,
203 .empty_tree = &empty_tree_oid,
204 .empty_blob = &empty_blob_oid,
205 .null_oid = &null_oid_sha1,
brian m. carlsonf50e7662017-11-12 21:28:52 +0000206 },
brian m. carlson13eeedb2018-11-14 04:09:36 +0000207 {
Ævar Arnfjörð Bjarmason0cb98722022-02-24 10:33:01 +0100208 .name = "sha256",
209 .format_id = GIT_SHA256_FORMAT_ID,
210 .rawsz = GIT_SHA256_RAWSZ,
211 .hexsz = GIT_SHA256_HEXSZ,
212 .blksz = GIT_SHA256_BLKSZ,
213 .init_fn = git_hash_sha256_init,
214 .clone_fn = git_hash_sha256_clone,
215 .update_fn = git_hash_sha256_update,
216 .final_fn = git_hash_sha256_final,
217 .final_oid_fn = git_hash_sha256_final_oid,
218 .empty_tree = &empty_tree_oid_sha256,
219 .empty_blob = &empty_blob_oid_sha256,
220 .null_oid = &null_oid_sha256,
brian m. carlson13eeedb2018-11-14 04:09:36 +0000221 }
brian m. carlsonf50e7662017-11-12 21:28:52 +0000222};
223
brian m. carlson14228442021-04-26 01:02:56 +0000224const struct object_id *null_oid(void)
225{
226 return the_hash_algo->null_oid;
227}
228
brian m. carlsond8a92ce2018-05-02 00:25:54 +0000229const char *empty_tree_oid_hex(void)
230{
231 static char buf[GIT_MAX_HEXSZ + 1];
232 return oid_to_hex_r(buf, the_hash_algo->empty_tree);
233}
234
235const char *empty_blob_oid_hex(void)
236{
237 static char buf[GIT_MAX_HEXSZ + 1];
238 return oid_to_hex_r(buf, the_hash_algo->empty_blob);
239}
240
brian m. carlson2f90b9d2018-10-22 02:43:32 +0000241int hash_algo_by_name(const char *name)
242{
243 int i;
244 if (!name)
245 return GIT_HASH_UNKNOWN;
246 for (i = 1; i < GIT_HASH_NALGOS; i++)
247 if (!strcmp(name, hash_algos[i].name))
248 return i;
249 return GIT_HASH_UNKNOWN;
250}
251
252int hash_algo_by_id(uint32_t format_id)
253{
254 int i;
255 for (i = 1; i < GIT_HASH_NALGOS; i++)
256 if (format_id == hash_algos[i].format_id)
257 return i;
258 return GIT_HASH_UNKNOWN;
259}
260
brian m. carlson95399782019-02-19 00:05:17 +0000261int hash_algo_by_length(int len)
262{
263 int i;
264 for (i = 1; i < GIT_HASH_NALGOS; i++)
265 if (len == hash_algos[i].rawsz)
266 return i;
267 return GIT_HASH_UNKNOWN;
268}
brian m. carlson2f90b9d2018-10-22 02:43:32 +0000269
Nguyễn Thái Ngọc Duyc597ba82011-02-05 21:03:01 +0700270/*
271 * This is meant to hold a *small* number of objects that you would
Jeff Kingcb1c8d12019-01-07 03:33:52 -0500272 * want read_object_file() to be able to return, but yet you do not want
Nguyễn Thái Ngọc Duyc597ba82011-02-05 21:03:01 +0700273 * to write them into the object store (e.g. a browse-only
274 * application).
275 */
276static struct cached_object {
brian m. carlson62ba93e2018-05-02 00:26:03 +0000277 struct object_id oid;
Nguyễn Thái Ngọc Duyc597ba82011-02-05 21:03:01 +0700278 enum object_type type;
279 void *buf;
280 unsigned long size;
281} *cached_objects;
282static int cached_object_nr, cached_object_alloc;
283
284static struct cached_object empty_tree = {
Ævar Arnfjörð Bjarmason50103642022-03-17 18:27:17 +0100285 .oid = {
286 .hash = EMPTY_TREE_SHA1_BIN_LITERAL,
287 },
288 .type = OBJ_TREE,
289 .buf = "",
Nguyễn Thái Ngọc Duyc597ba82011-02-05 21:03:01 +0700290};
291
brian m. carlson62ba93e2018-05-02 00:26:03 +0000292static struct cached_object *find_cached_object(const struct object_id *oid)
Nguyễn Thái Ngọc Duyc597ba82011-02-05 21:03:01 +0700293{
294 int i;
295 struct cached_object *co = cached_objects;
296
297 for (i = 0; i < cached_object_nr; i++, co++) {
Jeff King4a7e27e2018-08-28 17:22:40 -0400298 if (oideq(&co->oid, oid))
Nguyễn Thái Ngọc Duyc597ba82011-02-05 21:03:01 +0700299 return co;
300 }
Jeff King4a7e27e2018-08-28 17:22:40 -0400301 if (oideq(oid, the_hash_algo->empty_tree))
Nguyễn Thái Ngọc Duyc597ba82011-02-05 21:03:01 +0700302 return &empty_tree;
303 return NULL;
304}
305
Torsten Bögershausen94729352017-11-16 17:38:28 +0100306
Torsten Bögershausen8462ff42018-01-13 23:49:31 +0100307static int get_conv_flags(unsigned flags)
Torsten Bögershausen94729352017-11-16 17:38:28 +0100308{
309 if (flags & HASH_RENORMALIZE)
Torsten Bögershausen8462ff42018-01-13 23:49:31 +0100310 return CONV_EOL_RENORMALIZE;
Torsten Bögershausen94729352017-11-16 17:38:28 +0100311 else if (flags & HASH_WRITE_OBJECT)
Lars Schneider107642f2018-04-15 20:16:07 +0200312 return global_conv_flags_eol | CONV_WRITE_OBJECT;
Torsten Bögershausen94729352017-11-16 17:38:28 +0100313 else
Torsten Bögershausen8462ff42018-01-13 23:49:31 +0100314 return 0;
Torsten Bögershausen94729352017-11-16 17:38:28 +0100315}
316
317
Junio C Hamano90a64642011-03-10 16:02:50 -0800318int mkdir_in_gitdir(const char *path)
319{
320 if (mkdir(path, 0777)) {
321 int saved_errno = errno;
322 struct stat st;
323 struct strbuf sb = STRBUF_INIT;
324
325 if (errno != EEXIST)
326 return -1;
327 /*
328 * Are we looking at a path in a symlinked worktree
329 * whose original repository does not yet have it?
330 * e.g. .git/rr-cache pointing at its original
331 * repository in which the user hasn't performed any
332 * conflict resolution yet?
333 */
334 if (lstat(path, &st) || !S_ISLNK(st.st_mode) ||
335 strbuf_readlink(&sb, path, st.st_size) ||
336 !is_absolute_path(sb.buf) ||
337 mkdir(sb.buf, 0777)) {
338 strbuf_release(&sb);
339 errno = saved_errno;
340 return -1;
341 }
342 strbuf_release(&sb);
343 }
344 return adjust_shared_perm(path);
345}
346
Matheus Tavareseb3c0272020-12-01 20:45:04 -0300347static enum scld_error safe_create_leading_directories_1(char *path, int share)
Junio C Hamanob2cb9422005-07-06 01:11:52 -0700348{
Michael Haggerty26c8ae22014-01-06 14:45:22 +0100349 char *next_component = path + offset_1st_component(path);
Michael Haggerty0be05212014-01-06 14:45:25 +0100350 enum scld_error ret = SCLD_OK;
Jason Riedy67d42212006-02-09 17:56:13 -0800351
Michael Haggerty0be05212014-01-06 14:45:25 +0100352 while (ret == SCLD_OK && next_component) {
Michael Haggertyf0502332014-01-06 14:45:20 +0100353 struct stat st;
Michael Haggerty0f527402014-01-19 00:40:44 +0100354 char *slash = next_component, slash_character;
Michael Haggertyf0502332014-01-06 14:45:20 +0100355
Michael Haggerty0f527402014-01-19 00:40:44 +0100356 while (*slash && !is_dir_sep(*slash))
357 slash++;
358
359 if (!*slash)
Junio C Hamanob2cb9422005-07-06 01:11:52 -0700360 break;
Michael Haggertybf10cf72014-01-06 14:45:23 +0100361
Michael Haggerty26c8ae22014-01-06 14:45:22 +0100362 next_component = slash + 1;
Michael Haggerty0f527402014-01-19 00:40:44 +0100363 while (is_dir_sep(*next_component))
Michael Haggertybf10cf72014-01-06 14:45:23 +0100364 next_component++;
Michael Haggerty26c8ae22014-01-06 14:45:22 +0100365 if (!*next_component)
Junio C Hamano5f0bdf52008-09-02 14:10:15 -0700366 break;
Michael Haggerty831651f2014-01-06 14:45:21 +0100367
Michael Haggerty0f527402014-01-19 00:40:44 +0100368 slash_character = *slash;
Michael Haggerty831651f2014-01-06 14:45:21 +0100369 *slash = '\0';
Jason Riedy67d42212006-02-09 17:56:13 -0800370 if (!stat(path, &st)) {
371 /* path exists */
Michael Haggerty204a0472017-01-06 17:22:25 +0100372 if (!S_ISDIR(st.st_mode)) {
373 errno = ENOTDIR;
Michael Haggerty0be05212014-01-06 14:45:25 +0100374 ret = SCLD_EXISTS;
Michael Haggerty204a0472017-01-06 17:22:25 +0100375 }
Michael Haggerty53a39722014-01-06 14:45:19 +0100376 } else if (mkdir(path, 0777)) {
Steven Walter928734d2013-03-17 10:09:27 -0400377 if (errno == EEXIST &&
Michael Haggerty9e6f8852014-01-06 14:45:24 +0100378 !stat(path, &st) && S_ISDIR(st.st_mode))
Steven Walter928734d2013-03-17 10:09:27 -0400379 ; /* somebody created it since we checked */
Michael Haggerty18d37e82014-01-06 14:45:27 +0100380 else if (errno == ENOENT)
381 /*
382 * Either mkdir() failed because
383 * somebody just pruned the containing
384 * directory, or stat() failed because
385 * the file that was in our way was
386 * just removed. Either way, inform
387 * the caller that it might be worth
388 * trying again:
389 */
390 ret = SCLD_VANISHED;
Michael Haggerty9e6f8852014-01-06 14:45:24 +0100391 else
Michael Haggerty0be05212014-01-06 14:45:25 +0100392 ret = SCLD_FAILED;
Matheus Tavareseb3c0272020-12-01 20:45:04 -0300393 } else if (share && adjust_shared_perm(path)) {
Michael Haggerty0be05212014-01-06 14:45:25 +0100394 ret = SCLD_PERMS;
Jason Riedy67d42212006-02-09 17:56:13 -0800395 }
Michael Haggerty0f527402014-01-19 00:40:44 +0100396 *slash = slash_character;
Junio C Hamanob2cb9422005-07-06 01:11:52 -0700397 }
Michael Haggerty9e6f8852014-01-06 14:45:24 +0100398 return ret;
Junio C Hamanob2cb9422005-07-06 01:11:52 -0700399}
400
Matheus Tavareseb3c0272020-12-01 20:45:04 -0300401enum scld_error safe_create_leading_directories(char *path)
402{
403 return safe_create_leading_directories_1(path, 1);
404}
405
406enum scld_error safe_create_leading_directories_no_share(char *path)
407{
408 return safe_create_leading_directories_1(path, 0);
409}
410
Michael Haggerty0be05212014-01-06 14:45:25 +0100411enum scld_error safe_create_leading_directories_const(const char *path)
Jeff King8e21d632008-06-25 01:41:34 -0400412{
Michael Haggerty02944302017-01-06 17:22:24 +0100413 int save_errno;
Jeff King8e21d632008-06-25 01:41:34 -0400414 /* path points to cache entries, so xstrdup before messing with it */
415 char *buf = xstrdup(path);
Michael Haggerty0be05212014-01-06 14:45:25 +0100416 enum scld_error result = safe_create_leading_directories(buf);
Michael Haggerty02944302017-01-06 17:22:24 +0100417
418 save_errno = errno;
Jeff King8e21d632008-06-25 01:41:34 -0400419 free(buf);
Michael Haggerty02944302017-01-06 17:22:24 +0100420 errno = save_errno;
Jeff King8e21d632008-06-25 01:41:34 -0400421 return result;
422}
423
Jeff King514c5fd2019-01-07 03:35:42 -0500424static void fill_loose_path(struct strbuf *buf, const struct object_id *oid)
Junio C Hamanoace15342005-05-07 00:38:04 -0700425{
426 int i;
brian m. carlson94b5e092018-07-16 01:28:07 +0000427 for (i = 0; i < the_hash_algo->rawsz; i++) {
Junio C Hamanoace15342005-05-07 00:38:04 -0700428 static char hex[] = "0123456789abcdef";
Jeff King514c5fd2019-01-07 03:35:42 -0500429 unsigned int val = oid->hash[i];
Jeff Kingf7b77742016-10-03 16:36:09 -0400430 strbuf_addch(buf, hex[val >> 4]);
431 strbuf_addch(buf, hex[val & 0xf]);
Jeff Kingafbba2f2016-10-03 16:35:55 -0400432 if (!i)
Jeff Kingf7b77742016-10-03 16:36:09 -0400433 strbuf_addch(buf, '/');
Junio C Hamanoace15342005-05-07 00:38:04 -0700434 }
435}
436
Jeff Kingf0eaf632018-11-12 09:50:39 -0500437static const char *odb_loose_path(struct object_directory *odb,
438 struct strbuf *buf,
Jeff King514c5fd2019-01-07 03:35:42 -0500439 const struct object_id *oid)
Linus Torvalds0fcfd162005-04-18 13:04:43 -0700440{
Jeff Kingb69fb862018-11-12 09:48:56 -0500441 strbuf_reset(buf);
Jeff Kingf0eaf632018-11-12 09:50:39 -0500442 strbuf_addstr(buf, odb->path);
Christian Couder34498472018-01-18 11:08:54 +0100443 strbuf_addch(buf, '/');
Jeff King514c5fd2019-01-07 03:35:42 -0500444 fill_loose_path(buf, oid);
Jeff King38dbe5f2016-10-03 16:36:04 -0400445 return buf->buf;
Linus Torvalds0fcfd162005-04-18 13:04:43 -0700446}
447
Jeff Kingf3f043a2018-11-12 09:49:35 -0500448const char *loose_object_path(struct repository *r, struct strbuf *buf,
Jeff King514c5fd2019-01-07 03:35:42 -0500449 const struct object_id *oid)
Jeff Kingf3f043a2018-11-12 09:49:35 -0500450{
Jeff King514c5fd2019-01-07 03:35:42 -0500451 return odb_loose_path(r->objects->odb, buf, oid);
Jeff Kingf3f043a2018-11-12 09:49:35 -0500452}
453
Junio C Hamanoddd5d052005-05-08 13:51:13 -0700454/*
Jeff King4ea82472016-10-03 16:34:48 -0400455 * Return non-zero iff the path is usable as an alternate object database.
456 */
Stefan Beller13313fc2018-03-23 18:21:03 +0100457static int alt_odb_usable(struct raw_object_store *o,
458 struct strbuf *path,
Eric Wongcf2dc1c2021-07-07 23:10:15 +0000459 const char *normalized_objdir, khiter_t *pos)
Jeff King4ea82472016-10-03 16:34:48 -0400460{
Eric Wongcf2dc1c2021-07-07 23:10:15 +0000461 int r;
Jeff King4ea82472016-10-03 16:34:48 -0400462
463 /* Detect cases where alternate disappeared */
464 if (!is_directory(path->buf)) {
Nguyễn Thái Ngọc Duy259328b2018-07-21 09:49:39 +0200465 error(_("object directory %s does not exist; "
466 "check .git/objects/info/alternates"),
Jeff King4ea82472016-10-03 16:34:48 -0400467 path->buf);
468 return 0;
469 }
470
471 /*
472 * Prevent the common mistake of listing the same
473 * thing twice, or object directory itself.
474 */
Eric Wongcf2dc1c2021-07-07 23:10:15 +0000475 if (!o->odb_by_path) {
476 khiter_t p;
Jeff King4ea82472016-10-03 16:34:48 -0400477
Eric Wongcf2dc1c2021-07-07 23:10:15 +0000478 o->odb_by_path = kh_init_odb_path_map();
479 assert(!o->odb->next);
480 p = kh_put_odb_path_map(o->odb_by_path, o->odb->path, &r);
481 assert(r == 1); /* never used */
482 kh_value(o->odb_by_path, p) = o->odb;
483 }
484 if (fspatheq(path->buf, normalized_objdir))
485 return 0;
486 *pos = kh_put_odb_path_map(o->odb_by_path, path->buf, &r);
487 /* r: 0 = exists, 1 = never used, 2 = deleted */
488 return r == 0 ? 0 : 1;
Jeff King4ea82472016-10-03 16:34:48 -0400489}
490
491/*
Junio C Hamanoddd5d052005-05-08 13:51:13 -0700492 * Prepare alternate object database registry.
Junio C Hamanod5a63b92005-08-14 17:25:57 -0700493 *
494 * The variable alt_odb_list points at the list of struct
Jeff King263db402018-11-12 09:48:47 -0500495 * object_directory. The elements on this list come from
Junio C Hamanod5a63b92005-08-14 17:25:57 -0700496 * non-empty elements from colon separated ALTERNATE_DB_ENVIRONMENT
497 * environment variable, and $GIT_OBJECT_DIRECTORY/info/alternates,
Junio C Hamano1494e032005-12-04 22:48:43 -0800498 * whose contents is similar to that environment variable but can be
499 * LF separated. Its base points at a statically allocated buffer that
Junio C Hamanod5a63b92005-08-14 17:25:57 -0700500 * contains "/the/directory/corresponding/to/.git/objects/...", while
501 * its name points just after the slash at the end of ".git/objects/"
Martin Ågrene5afd442020-12-31 12:56:21 +0100502 * in the example above, and has enough space to hold all hex characters
503 * of the object ID, an extra slash for the first level indirection, and
504 * the terminating NUL.
Junio C Hamanoddd5d052005-05-08 13:51:13 -0700505 */
Stefan Beller77f012e2018-03-23 18:21:08 +0100506static void read_info_alternates(struct repository *r,
507 const char *relative_base,
508 int depth);
Eric Wong407532f2021-07-07 23:10:16 +0000509static int link_alt_odb_entry(struct repository *r, const struct strbuf *entry,
Stefan Bellercfc62fc2018-03-23 18:21:04 +0100510 const char *relative_base, int depth, const char *normalized_objdir)
Martin Waitzc2f493a2006-05-07 20:19:21 +0200511{
Jeff King263db402018-11-12 09:48:47 -0500512 struct object_directory *ent;
Hui Wang5bdf0a82011-09-07 18:37:47 +0800513 struct strbuf pathbuf = STRBUF_INIT;
Glen Choo199337d2022-11-24 00:55:31 +0000514 struct strbuf tmp = STRBUF_INIT;
Eric Wongcf2dc1c2021-07-07 23:10:15 +0000515 khiter_t pos;
Glen Choo199337d2022-11-24 00:55:31 +0000516 int ret = -1;
Martin Waitzc2f493a2006-05-07 20:19:21 +0200517
Eric Wong407532f2021-07-07 23:10:16 +0000518 if (!is_absolute_path(entry->buf) && relative_base) {
Brandon Williams4ac90062016-12-12 10:16:55 -0800519 strbuf_realpath(&pathbuf, relative_base, 1);
Hui Wang5bdf0a82011-09-07 18:37:47 +0800520 strbuf_addch(&pathbuf, '/');
Martin Waitzc2f493a2006-05-07 20:19:21 +0200521 }
Eric Wong407532f2021-07-07 23:10:16 +0000522 strbuf_addbuf(&pathbuf, entry);
Hui Wang5bdf0a82011-09-07 18:37:47 +0800523
Glen Choo199337d2022-11-24 00:55:31 +0000524 if (!strbuf_realpath(&tmp, pathbuf.buf, 0)) {
Nguyễn Thái Ngọc Duy259328b2018-07-21 09:49:39 +0200525 error(_("unable to normalize alternate object path: %s"),
Jeff King670c3592016-10-03 16:34:17 -0400526 pathbuf.buf);
Glen Choo199337d2022-11-24 00:55:31 +0000527 goto error;
Jeff King670c3592016-10-03 16:34:17 -0400528 }
Glen Choo199337d2022-11-24 00:55:31 +0000529 strbuf_swap(&pathbuf, &tmp);
Hui Wang5bdf0a82011-09-07 18:37:47 +0800530
531 /*
532 * The trailing slash after the directory name is given by
533 * this function at the end. Remove duplicates.
534 */
Jeff King4ea82472016-10-03 16:34:48 -0400535 while (pathbuf.len && pathbuf.buf[pathbuf.len - 1] == '/')
536 strbuf_setlen(&pathbuf, pathbuf.len - 1);
Hui Wang5bdf0a82011-09-07 18:37:47 +0800537
Glen Choo199337d2022-11-24 00:55:31 +0000538 if (!alt_odb_usable(r->objects, &pathbuf, normalized_objdir, &pos))
539 goto error;
Martin Waitzc2f493a2006-05-07 20:19:21 +0200540
René Scharfeca56dad2021-03-13 17:17:22 +0100541 CALLOC_ARRAY(ent, 1);
Eric Wongcf2dc1c2021-07-07 23:10:15 +0000542 /* pathbuf.buf is already in r->objects->odb_by_path */
543 ent->path = strbuf_detach(&pathbuf, NULL);
Martin Waitzc2f493a2006-05-07 20:19:21 +0200544
545 /* add the alternate entry */
Jeff Kingf0eaf632018-11-12 09:50:39 -0500546 *r->objects->odb_tail = ent;
547 r->objects->odb_tail = &(ent->next);
Martin Waitzc2f493a2006-05-07 20:19:21 +0200548 ent->next = NULL;
Eric Wongcf2dc1c2021-07-07 23:10:15 +0000549 assert(r->objects->odb_by_path);
550 kh_value(r->objects->odb_by_path, pos) = ent;
Martin Waitzc2f493a2006-05-07 20:19:21 +0200551
552 /* recursively add alternates */
Eric Wongcf2dc1c2021-07-07 23:10:15 +0000553 read_info_alternates(r, ent->path, depth + 1);
Glen Choo199337d2022-11-24 00:55:31 +0000554 ret = 0;
555 error:
556 strbuf_release(&tmp);
557 strbuf_release(&pathbuf);
558 return ret;
Martin Waitzc2f493a2006-05-07 20:19:21 +0200559}
560
Jeff Kingcf3c6352016-12-12 14:52:22 -0500561static const char *parse_alt_odb_entry(const char *string,
562 int sep,
563 struct strbuf *out)
564{
565 const char *end;
566
567 strbuf_reset(out);
568
569 if (*string == '#') {
570 /* comment; consume up to next separator */
571 end = strchrnul(string, sep);
572 } else if (*string == '"' && !unquote_c_style(out, string, &end)) {
573 /*
574 * quoted path; unquote_c_style has copied the
575 * data for us and set "end". Broken quoting (e.g.,
576 * an entry that doesn't end with a quote) falls
577 * back to the unquoted case below.
578 */
579 } else {
580 /* normal, unquoted path */
581 end = strchrnul(string, sep);
582 strbuf_add(out, string, end - string);
583 }
584
585 if (*end)
586 end++;
587 return end;
588}
589
Stefan Beller77f012e2018-03-23 18:21:08 +0100590static void link_alt_odb_entries(struct repository *r, const char *alt,
591 int sep, const char *relative_base, int depth)
Junio C Hamanod5a63b92005-08-14 17:25:57 -0700592{
Ephrim Khong539e7502014-07-15 13:29:45 +0200593 struct strbuf objdirbuf = STRBUF_INIT;
Jeff Kingcf3c6352016-12-12 14:52:22 -0500594 struct strbuf entry = STRBUF_INIT;
Martin Waitzc2f493a2006-05-07 20:19:21 +0200595
Jeff Kingf28e3662017-11-12 10:27:39 +0000596 if (!alt || !*alt)
597 return;
598
Martin Waitzc2f493a2006-05-07 20:19:21 +0200599 if (depth > 5) {
Nguyễn Thái Ngọc Duy259328b2018-07-21 09:49:39 +0200600 error(_("%s: ignoring alternate object stores, nesting too deep"),
Martin Waitzc2f493a2006-05-07 20:19:21 +0200601 relative_base);
602 return;
603 }
Junio C Hamanod5a63b92005-08-14 17:25:57 -0700604
Glen Choo199337d2022-11-24 00:55:31 +0000605 strbuf_realpath(&objdirbuf, r->objects->odb->path, 1);
Ephrim Khong539e7502014-07-15 13:29:45 +0200606
Jeff Kingcf3c6352016-12-12 14:52:22 -0500607 while (*alt) {
608 alt = parse_alt_odb_entry(alt, sep, &entry);
609 if (!entry.len)
Junio C Hamano9577e7e2005-08-16 18:22:05 -0700610 continue;
Eric Wong407532f2021-07-07 23:10:16 +0000611 link_alt_odb_entry(r, &entry,
Stefan Bellercfc62fc2018-03-23 18:21:04 +0100612 relative_base, depth, objdirbuf.buf);
Junio C Hamano9577e7e2005-08-16 18:22:05 -0700613 }
Jeff Kingcf3c6352016-12-12 14:52:22 -0500614 strbuf_release(&entry);
Ephrim Khong539e7502014-07-15 13:29:45 +0200615 strbuf_release(&objdirbuf);
Junio C Hamanod5a63b92005-08-14 17:25:57 -0700616}
617
Stefan Beller77f012e2018-03-23 18:21:08 +0100618static void read_info_alternates(struct repository *r,
619 const char *relative_base,
620 int depth)
Junio C Hamanoace15342005-05-07 00:38:04 -0700621{
Jeff King5015f012015-08-19 14:12:45 -0400622 char *path;
Jeff Kingdc732bd2017-09-19 15:41:07 -0400623 struct strbuf buf = STRBUF_INIT;
Jason Riedyc7c81b32005-08-23 13:34:07 -0700624
Jeff King5015f012015-08-19 14:12:45 -0400625 path = xstrfmt("%s/info/alternates", relative_base);
Jeff Kingdc732bd2017-09-19 15:41:07 -0400626 if (strbuf_read_file(&buf, path, 1024) < 0) {
Jeff Kingf0f7beb2017-09-19 15:41:10 -0400627 warn_on_fopen_errors(path);
Jeff Kingdc732bd2017-09-19 15:41:07 -0400628 free(path);
Junio C Hamanod5a63b92005-08-14 17:25:57 -0700629 return;
Junio C Hamanoace15342005-05-07 00:38:04 -0700630 }
Junio C Hamanod5a63b92005-08-14 17:25:57 -0700631
Stefan Beller77f012e2018-03-23 18:21:08 +0100632 link_alt_odb_entries(r, buf.buf, '\n', relative_base, depth);
Jeff Kingdc732bd2017-09-19 15:41:07 -0400633 strbuf_release(&buf);
634 free(path);
Junio C Hamanoace15342005-05-07 00:38:04 -0700635}
636
Daniel Barkalowbef70b22008-04-17 19:32:30 -0400637void add_to_alternates_file(const char *reference)
638{
Martin Ågrenf132a122017-10-05 22:32:03 +0200639 struct lock_file lock = LOCK_INIT;
Jeff King77b9b1d2015-08-10 05:34:46 -0400640 char *alts = git_pathdup("objects/info/alternates");
641 FILE *in, *out;
Martin Ågrenf132a122017-10-05 22:32:03 +0200642 int found = 0;
Jeff King77b9b1d2015-08-10 05:34:46 -0400643
Martin Ågrenf132a122017-10-05 22:32:03 +0200644 hold_lock_file_for_update(&lock, alts, LOCK_DIE_ON_ERROR);
645 out = fdopen_lock_file(&lock, "w");
Jeff King77b9b1d2015-08-10 05:34:46 -0400646 if (!out)
Nguyễn Thái Ngọc Duy259328b2018-07-21 09:49:39 +0200647 die_errno(_("unable to fdopen alternates lockfile"));
Jeff King77b9b1d2015-08-10 05:34:46 -0400648
649 in = fopen(alts, "r");
650 if (in) {
651 struct strbuf line = STRBUF_INIT;
Jeff King77b9b1d2015-08-10 05:34:46 -0400652
Junio C Hamano3f163962015-10-28 13:29:24 -0700653 while (strbuf_getline(&line, in) != EOF) {
Jeff King77b9b1d2015-08-10 05:34:46 -0400654 if (!strcmp(reference, line.buf)) {
655 found = 1;
656 break;
657 }
658 fprintf_or_die(out, "%s\n", line.buf);
659 }
660
661 strbuf_release(&line);
662 fclose(in);
Jeff King77b9b1d2015-08-10 05:34:46 -0400663 }
664 else if (errno != ENOENT)
Nguyễn Thái Ngọc Duy259328b2018-07-21 09:49:39 +0200665 die_errno(_("unable to read alternates file"));
Jeff King77b9b1d2015-08-10 05:34:46 -0400666
Martin Ågrenf132a122017-10-05 22:32:03 +0200667 if (found) {
668 rollback_lock_file(&lock);
669 } else {
Jeff King77b9b1d2015-08-10 05:34:46 -0400670 fprintf_or_die(out, "%s\n", reference);
Martin Ågrenf132a122017-10-05 22:32:03 +0200671 if (commit_lock_file(&lock))
Nguyễn Thái Ngọc Duy259328b2018-07-21 09:49:39 +0200672 die_errno(_("unable to move new alternates file into place"));
Jeff Kingf0eaf632018-11-12 09:50:39 -0500673 if (the_repository->objects->loaded_alternates)
Stefan Beller93d8d1e2018-03-23 18:21:06 +0100674 link_alt_odb_entries(the_repository, reference,
675 '\n', NULL, 0);
Jeff King77b9b1d2015-08-10 05:34:46 -0400676 }
677 free(alts);
Daniel Barkalowbef70b22008-04-17 19:32:30 -0400678}
679
Jeff Kinga5b34d22016-10-03 16:35:03 -0400680void add_to_alternates_memory(const char *reference)
681{
682 /*
683 * Make sure alternates are initialized, or else our entry may be
684 * overwritten when they are.
685 */
Stefan Beller0b209032018-03-23 18:21:07 +0100686 prepare_alt_odb(the_repository);
Jeff Kinga5b34d22016-10-03 16:35:03 -0400687
Stefan Beller93d8d1e2018-03-23 18:21:06 +0100688 link_alt_odb_entries(the_repository, reference,
689 '\n', NULL, 0);
Jeff Kinga5b34d22016-10-03 16:35:03 -0400690}
691
Neeraj Singhb3cecf42021-12-06 22:05:04 +0000692struct object_directory *set_temporary_primary_odb(const char *dir, int will_destroy)
693{
694 struct object_directory *new_odb;
695
696 /*
697 * Make sure alternates are initialized, or else our entry may be
698 * overwritten when they are.
699 */
700 prepare_alt_odb(the_repository);
701
702 /*
703 * Make a new primary odb and link the old primary ODB in as an
704 * alternate
705 */
706 new_odb = xcalloc(1, sizeof(*new_odb));
707 new_odb->path = xstrdup(dir);
Neeraj Singhecd81df2021-12-06 22:05:05 +0000708
709 /*
710 * Disable ref updates while a temporary odb is active, since
711 * the objects in the database may roll back.
712 */
713 new_odb->disable_ref_updates = 1;
Neeraj Singhb3cecf42021-12-06 22:05:04 +0000714 new_odb->will_destroy = will_destroy;
715 new_odb->next = the_repository->objects->odb;
716 the_repository->objects->odb = new_odb;
717 return new_odb->next;
718}
719
720void restore_primary_odb(struct object_directory *restore_odb, const char *old_path)
721{
722 struct object_directory *cur_odb = the_repository->objects->odb;
723
724 if (strcmp(old_path, cur_odb->path))
725 BUG("expected %s as primary object store; found %s",
726 old_path, cur_odb->path);
727
728 if (cur_odb->next != restore_odb)
729 BUG("we expect the old primary object store to be the first alternate");
730
731 the_repository->objects->odb = restore_odb;
732 free_object_directory(cur_odb);
733}
734
Stefan Beller9eeea7d2016-08-15 14:53:24 -0700735/*
736 * Compute the exact path an alternate is at and returns it. In case of
737 * error NULL is returned and the human readable error is added to `err`
Robert P. J. Dayefde7b72018-06-03 10:32:50 -0400738 * `path` may be relative and should point to $GIT_DIR.
Stefan Beller9eeea7d2016-08-15 14:53:24 -0700739 * `err` must not be null.
740 */
741char *compute_alternate_path(const char *path, struct strbuf *err)
742{
743 char *ref_git = NULL;
Alexandr Miloslavskiy4530a852020-03-10 13:11:23 +0000744 const char *repo;
Stefan Beller9eeea7d2016-08-15 14:53:24 -0700745 int seen_error = 0;
746
Alexandr Miloslavskiy4530a852020-03-10 13:11:23 +0000747 ref_git = real_pathdup(path, 0);
748 if (!ref_git) {
Stefan Beller9eeea7d2016-08-15 14:53:24 -0700749 seen_error = 1;
750 strbuf_addf(err, _("path '%s' does not exist"), path);
751 goto out;
Alexandr Miloslavskiy4530a852020-03-10 13:11:23 +0000752 }
Stefan Beller9eeea7d2016-08-15 14:53:24 -0700753
754 repo = read_gitfile(ref_git);
755 if (!repo)
756 repo = read_gitfile(mkpath("%s/.git", ref_git));
757 if (repo) {
758 free(ref_git);
759 ref_git = xstrdup(repo);
760 }
761
762 if (!repo && is_directory(mkpath("%s/.git/objects", ref_git))) {
763 char *ref_git_git = mkpathdup("%s/.git", ref_git);
764 free(ref_git);
765 ref_git = ref_git_git;
766 } else if (!is_directory(mkpath("%s/objects", ref_git))) {
767 struct strbuf sb = STRBUF_INIT;
768 seen_error = 1;
769 if (get_common_dir(&sb, ref_git)) {
770 strbuf_addf(err,
771 _("reference repository '%s' as a linked "
772 "checkout is not supported yet."),
773 path);
774 goto out;
775 }
776
777 strbuf_addf(err, _("reference repository '%s' is not a "
778 "local repository."), path);
779 goto out;
780 }
781
782 if (!access(mkpath("%s/shallow", ref_git), F_OK)) {
783 strbuf_addf(err, _("reference repository '%s' is shallow"),
784 path);
785 seen_error = 1;
786 goto out;
787 }
788
789 if (!access(mkpath("%s/info/grafts", ref_git), F_OK)) {
790 strbuf_addf(err,
791 _("reference repository '%s' is grafted"),
792 path);
793 seen_error = 1;
794 goto out;
795 }
796
797out:
798 if (seen_error) {
Ævar Arnfjörð Bjarmason6a83d902017-06-15 23:15:46 +0000799 FREE_AND_NULL(ref_git);
Stefan Beller9eeea7d2016-08-15 14:53:24 -0700800 }
801
802 return ref_git;
803}
804
Taylor Blauf57a7392021-09-01 16:34:01 -0400805struct object_directory *find_odb(struct repository *r, const char *obj_dir)
806{
807 struct object_directory *odb;
808 char *obj_dir_real = real_pathdup(obj_dir, 1);
809 struct strbuf odb_path_real = STRBUF_INIT;
810
811 prepare_alt_odb(r);
812 for (odb = r->objects->odb; odb; odb = odb->next) {
813 strbuf_realpath(&odb_path_real, odb->path, 1);
814 if (!strcmp(obj_dir_real, odb_path_real.buf))
815 break;
816 }
817
818 free(obj_dir_real);
819 strbuf_release(&odb_path_real);
820
821 if (!odb)
822 die(_("could not find object directory matching %s"), obj_dir);
823 return odb;
824}
825
Jeff King709dfa62019-07-01 09:17:40 -0400826static void fill_alternate_refs_command(struct child_process *cmd,
827 const char *repo_path)
828{
829 const char *value;
830
831 if (!git_config_get_value("core.alternateRefsCommand", &value)) {
832 cmd->use_shell = 1;
833
Jeff Kingc972bf42020-07-28 16:25:12 -0400834 strvec_push(&cmd->args, value);
835 strvec_push(&cmd->args, repo_path);
Jeff King709dfa62019-07-01 09:17:40 -0400836 } else {
837 cmd->git_cmd = 1;
838
Jeff Kingc972bf42020-07-28 16:25:12 -0400839 strvec_pushf(&cmd->args, "--git-dir=%s", repo_path);
840 strvec_push(&cmd->args, "for-each-ref");
841 strvec_push(&cmd->args, "--format=%(objectname)");
Jeff King709dfa62019-07-01 09:17:40 -0400842
843 if (!git_config_get_value("core.alternateRefsPrefixes", &value)) {
Jeff Kingc972bf42020-07-28 16:25:12 -0400844 strvec_push(&cmd->args, "--");
845 strvec_split(&cmd->args, value);
Jeff King709dfa62019-07-01 09:17:40 -0400846 }
847 }
848
Ævar Arnfjörð Bjarmason29fda242022-06-02 11:09:50 +0200849 strvec_pushv(&cmd->env, (const char **)local_repo_env);
Jeff King709dfa62019-07-01 09:17:40 -0400850 cmd->out = -1;
851}
852
853static void read_alternate_refs(const char *path,
854 alternate_ref_fn *cb,
855 void *data)
856{
857 struct child_process cmd = CHILD_PROCESS_INIT;
858 struct strbuf line = STRBUF_INIT;
859 FILE *fh;
860
861 fill_alternate_refs_command(&cmd, path);
862
863 if (start_command(&cmd))
864 return;
865
866 fh = xfdopen(cmd.out, "r");
867 while (strbuf_getline_lf(&line, fh) != EOF) {
868 struct object_id oid;
869 const char *p;
870
871 if (parse_oid_hex(line.buf, &oid, &p) || *p) {
872 warning(_("invalid line while parsing alternate refs: %s"),
873 line.buf);
874 break;
875 }
876
877 cb(&oid, data);
878 }
879
880 fclose(fh);
881 finish_command(&cmd);
René Scharfe86ad3ea2019-08-07 13:15:25 +0200882 strbuf_release(&line);
Jeff King709dfa62019-07-01 09:17:40 -0400883}
884
885struct alternate_refs_data {
886 alternate_ref_fn *fn;
887 void *data;
888};
889
890static int refs_from_alternate_cb(struct object_directory *e,
891 void *data)
892{
893 struct strbuf path = STRBUF_INIT;
894 size_t base_len;
895 struct alternate_refs_data *cb = data;
896
897 if (!strbuf_realpath(&path, e->path, 0))
898 goto out;
899 if (!strbuf_strip_suffix(&path, "/objects"))
900 goto out;
901 base_len = path.len;
902
903 /* Is this a git repository with refs? */
904 strbuf_addstr(&path, "/refs");
905 if (!is_directory(path.buf))
906 goto out;
907 strbuf_setlen(&path, base_len);
908
909 read_alternate_refs(path.buf, cb->fn, cb->data);
910
911out:
912 strbuf_release(&path);
913 return 0;
914}
915
916void for_each_alternate_ref(alternate_ref_fn fn, void *data)
917{
918 struct alternate_refs_data cb;
919 cb.fn = fn;
920 cb.data = data;
921 foreach_alt_odb(refs_from_alternate_cb, &cb);
922}
923
Jeff Kingfe1b2262014-10-15 18:33:13 -0400924int foreach_alt_odb(alt_odb_fn fn, void *cb)
Junio C Hamanod79796b2008-09-09 01:27:10 -0700925{
Jeff King263db402018-11-12 09:48:47 -0500926 struct object_directory *ent;
Jeff Kingfe1b2262014-10-15 18:33:13 -0400927 int r = 0;
Junio C Hamanod79796b2008-09-09 01:27:10 -0700928
Stefan Beller0b209032018-03-23 18:21:07 +0100929 prepare_alt_odb(the_repository);
Jeff Kingf0eaf632018-11-12 09:50:39 -0500930 for (ent = the_repository->objects->odb->next; ent; ent = ent->next) {
Jeff Kingfe1b2262014-10-15 18:33:13 -0400931 r = fn(ent, cb);
932 if (r)
933 break;
934 }
935 return r;
Junio C Hamanod79796b2008-09-09 01:27:10 -0700936}
937
Stefan Beller13068bf2018-03-23 18:21:09 +0100938void prepare_alt_odb(struct repository *r)
Martin Waitzc2f493a2006-05-07 20:19:21 +0200939{
Jeff Kingf0eaf632018-11-12 09:50:39 -0500940 if (r->objects->loaded_alternates)
Shawn O. Pearce7dc24aa2007-05-26 01:24:40 -0400941 return;
942
Stefan Beller13068bf2018-03-23 18:21:09 +0100943 link_alt_odb_entries(r, r->objects->alternate_db, PATH_SEP, NULL, 0);
Martin Waitzc2f493a2006-05-07 20:19:21 +0200944
Jeff Kingf0eaf632018-11-12 09:50:39 -0500945 read_info_alternates(r, r->objects->odb->path, 0);
946 r->objects->loaded_alternates = 1;
Martin Waitzc2f493a2006-05-07 20:19:21 +0200947}
948
Jeff King3096b2e2015-07-08 16:33:52 -0400949/* Returns 1 if we have successfully freshened the file, 0 otherwise. */
Jeff King33d42212014-10-15 18:42:22 -0400950static int freshen_file(const char *fn)
Junio C Hamanoace15342005-05-07 00:38:04 -0700951{
luciano.rocha@booking.com312cd762020-04-14 16:27:26 +0200952 return !utime(fn, NULL);
Brandon Casey0f4dc142008-11-09 23:59:57 -0600953}
Junio C Hamanoace15342005-05-07 00:38:04 -0700954
Jeff King3096b2e2015-07-08 16:33:52 -0400955/*
956 * All of the check_and_freshen functions return 1 if the file exists and was
957 * freshened (if freshening was requested), 0 otherwise. If they return
958 * 0, you should not assume that it is safe to skip a write of the object (it
959 * either does not exist on disk, or has a stale mtime and may be subject to
960 * pruning).
961 */
Christian Couder6a5e6f52017-02-27 19:00:11 +0100962int check_and_freshen_file(const char *fn, int freshen)
Jeff King33d42212014-10-15 18:42:22 -0400963{
964 if (access(fn, F_OK))
965 return 0;
Jeff King3096b2e2015-07-08 16:33:52 -0400966 if (freshen && !freshen_file(fn))
Jeff King33d42212014-10-15 18:42:22 -0400967 return 0;
968 return 1;
969}
970
Jeff Kingf0eaf632018-11-12 09:50:39 -0500971static int check_and_freshen_odb(struct object_directory *odb,
972 const struct object_id *oid,
973 int freshen)
974{
975 static struct strbuf path = STRBUF_INIT;
Jeff King514c5fd2019-01-07 03:35:42 -0500976 odb_loose_path(odb, &path, oid);
Jeff Kingf0eaf632018-11-12 09:50:39 -0500977 return check_and_freshen_file(path.buf, freshen);
978}
979
brian m. carlson6862ebb2018-05-02 00:25:34 +0000980static int check_and_freshen_local(const struct object_id *oid, int freshen)
Jeff King33d42212014-10-15 18:42:22 -0400981{
Jeff Kingf0eaf632018-11-12 09:50:39 -0500982 return check_and_freshen_odb(the_repository->objects->odb, oid, freshen);
Jeff King33d42212014-10-15 18:42:22 -0400983}
984
brian m. carlson6862ebb2018-05-02 00:25:34 +0000985static int check_and_freshen_nonlocal(const struct object_id *oid, int freshen)
Brandon Casey0f4dc142008-11-09 23:59:57 -0600986{
Jeff King263db402018-11-12 09:48:47 -0500987 struct object_directory *odb;
Jeff Kingf3f043a2018-11-12 09:49:35 -0500988
Stefan Beller0b209032018-03-23 18:21:07 +0100989 prepare_alt_odb(the_repository);
Jeff Kingf0eaf632018-11-12 09:50:39 -0500990 for (odb = the_repository->objects->odb->next; odb; odb = odb->next) {
991 if (check_and_freshen_odb(odb, oid, freshen))
Linus Torvaldsc529d752008-06-14 11:43:01 -0700992 return 1;
Junio C Hamanoace15342005-05-07 00:38:04 -0700993 }
Linus Torvaldsc529d752008-06-14 11:43:01 -0700994 return 0;
Junio C Hamanoace15342005-05-07 00:38:04 -0700995}
996
brian m. carlson6862ebb2018-05-02 00:25:34 +0000997static int check_and_freshen(const struct object_id *oid, int freshen)
Jeff King33d42212014-10-15 18:42:22 -0400998{
brian m. carlson6862ebb2018-05-02 00:25:34 +0000999 return check_and_freshen_local(oid, freshen) ||
1000 check_and_freshen_nonlocal(oid, freshen);
Jeff King33d42212014-10-15 18:42:22 -04001001}
1002
brian m. carlson6862ebb2018-05-02 00:25:34 +00001003int has_loose_object_nonlocal(const struct object_id *oid)
Jeff King33d42212014-10-15 18:42:22 -04001004{
brian m. carlson6862ebb2018-05-02 00:25:34 +00001005 return check_and_freshen_nonlocal(oid, 0);
Jeff King33d42212014-10-15 18:42:22 -04001006}
1007
Taylor Blaub7573532022-05-20 19:17:52 -04001008int has_loose_object(const struct object_id *oid)
Brandon Casey0f4dc142008-11-09 23:59:57 -06001009{
brian m. carlson6862ebb2018-05-02 00:25:34 +00001010 return check_and_freshen(oid, 0);
Brandon Casey0f4dc142008-11-09 23:59:57 -06001011}
1012
Steffen Prohaska02710222014-08-26 17:23:23 +02001013static void mmap_limit_check(size_t length)
1014{
1015 static size_t limit = 0;
1016 if (!limit) {
1017 limit = git_env_ulong("GIT_MMAP_LIMIT", 0);
1018 if (!limit)
1019 limit = SIZE_MAX;
1020 }
1021 if (length > limit)
Nguyễn Thái Ngọc Duy259328b2018-07-21 09:49:39 +02001022 die(_("attempting to mmap %"PRIuMAX" over limit %"PRIuMAX),
Steffen Prohaska02710222014-08-26 17:23:23 +02001023 (uintmax_t)length, (uintmax_t)limit);
1024}
1025
Jeff King15708562015-05-28 03:56:15 -04001026void *xmmap_gently(void *start, size_t length,
1027 int prot, int flags, int fd, off_t offset)
Jonathan Nieder58ecbd52010-11-06 06:44:11 -05001028{
Steffen Prohaska02710222014-08-26 17:23:23 +02001029 void *ret;
1030
1031 mmap_limit_check(length);
1032 ret = mmap(start, length, prot, flags, fd, offset);
Jeff King9827d4c2019-08-12 16:50:21 -04001033 if (ret == MAP_FAILED && !length)
1034 ret = NULL;
Jonathan Nieder58ecbd52010-11-06 06:44:11 -05001035 return ret;
1036}
1037
Eric Wongdc059292021-06-30 00:01:32 +00001038const char *mmap_os_err(void)
1039{
1040 static const char blank[] = "";
1041#if defined(__linux__)
1042 if (errno == ENOMEM) {
1043 /* this continues an existing error message: */
1044 static const char enomem[] =
1045", check sys.vm.max_map_count and/or RLIMIT_DATA";
1046 return enomem;
1047 }
1048#endif /* OS-specific bits */
1049 return blank;
1050}
1051
Jeff King15708562015-05-28 03:56:15 -04001052void *xmmap(void *start, size_t length,
1053 int prot, int flags, int fd, off_t offset)
1054{
1055 void *ret = xmmap_gently(start, length, prot, flags, fd, offset);
1056 if (ret == MAP_FAILED)
Eric Wongdc059292021-06-30 00:01:32 +00001057 die_errno(_("mmap failed%s"), mmap_os_err());
Jeff King15708562015-05-28 03:56:15 -04001058 return ret;
1059}
1060
Ævar Arnfjörð Bjarmasonb04cdea2022-02-05 00:48:25 +01001061static int format_object_header_literally(char *str, size_t size,
1062 const char *type, size_t objsize)
Linus Torvalds0fcfd162005-04-18 13:04:43 -07001063{
Ævar Arnfjörð Bjarmasonb04cdea2022-02-05 00:48:25 +01001064 return xsnprintf(str, size, "%s %"PRIuMAX, type, (uintmax_t)objsize) + 1;
1065}
1066
1067int format_object_header(char *str, size_t size, enum object_type type,
1068 size_t objsize)
1069{
1070 const char *name = type_name(type);
1071
1072 if (!name)
1073 BUG("could not get a type name for 'enum object_type' value %d", type);
1074
1075 return format_object_header_literally(str, size, name, objsize);
1076}
1077
Linus Torvalds0fcfd162005-04-18 13:04:43 -07001078int check_object_signature(struct repository *r, const struct object_id *oid,
Ævar Arnfjörð Bjarmason44439c12022-02-05 00:48:32 +01001079 void *buf, unsigned long size,
1080 enum object_type type)
Linus Torvalds0fcfd162005-04-18 13:04:43 -07001081{
Ævar Arnfjörð Bjarmason0f156db2022-02-05 00:48:30 +01001082 struct object_id real_oid;
1083
1084 hash_object_file(r->hash_algo, buf, size, type, &real_oid);
1085
1086 return !oideq(oid, &real_oid) ? -1 : 0;
1087}
1088
1089int stream_object_signature(struct repository *r, const struct object_id *oid)
1090{
1091 struct object_id real_oid;
1092 unsigned long size;
Nguyễn Thái Ngọc Duy090ea122012-03-07 17:54:18 +07001093 enum object_type obj_type;
1094 struct git_istream *st;
brian m. carlson18e25882018-02-01 02:18:41 +00001095 git_hash_ctx c;
brian m. carlson1af64f72018-03-12 02:27:55 +00001096 char hdr[MAX_HEADER_LEN];
Nguyễn Thái Ngọc Duy090ea122012-03-07 17:54:18 +07001097 int hdrlen;
1098
Matheus Tavaresb98d1882020-01-30 17:32:23 -03001099 st = open_istream(r, oid, &obj_type, &size, NULL);
Nguyễn Thái Ngọc Duy090ea122012-03-07 17:54:18 +07001100 if (!st)
1101 return -1;
1102
1103 /* Generate the header */
Ævar Arnfjörð Bjarmasonb04cdea2022-02-05 00:48:25 +01001104 hdrlen = format_object_header(hdr, sizeof(hdr), obj_type, size);
Nguyễn Thái Ngọc Duy090ea122012-03-07 17:54:18 +07001105
1106 /* Sha1.. */
Matheus Tavaresb98d1882020-01-30 17:32:23 -03001107 r->hash_algo->init_fn(&c);
1108 r->hash_algo->update_fn(&c, hdr, hdrlen);
Nguyễn Thái Ngọc Duy090ea122012-03-07 17:54:18 +07001109 for (;;) {
1110 char buf[1024 * 16];
1111 ssize_t readlen = read_istream(st, buf, sizeof(buf));
1112
Jeff Kingf54fac52013-03-25 16:17:17 -04001113 if (readlen < 0) {
1114 close_istream(st);
1115 return -1;
1116 }
Nguyễn Thái Ngọc Duy090ea122012-03-07 17:54:18 +07001117 if (!readlen)
1118 break;
Matheus Tavaresb98d1882020-01-30 17:32:23 -03001119 r->hash_algo->update_fn(&c, buf, readlen);
Nguyễn Thái Ngọc Duy090ea122012-03-07 17:54:18 +07001120 }
Ævar Arnfjörð Bjarmason0f156db2022-02-05 00:48:30 +01001121 r->hash_algo->final_oid_fn(&real_oid, &c);
Nguyễn Thái Ngọc Duy090ea122012-03-07 17:54:18 +07001122 close_istream(st);
Ævar Arnfjörð Bjarmason0f156db2022-02-05 00:48:30 +01001123 return !oideq(oid, &real_oid) ? -1 : 0;
Linus Torvalds0fcfd162005-04-18 13:04:43 -07001124}
1125
Junio C Hamano1b8ac5e2016-10-28 06:23:07 -07001126int git_open_cloexec(const char *name, int flags)
Linus Torvalds44d1c192008-06-14 11:32:37 -07001127{
Junio C Hamano1e3001a2016-10-31 10:41:41 -07001128 int fd;
1129 static int o_cloexec = O_CLOEXEC;
Linus Torvalds44d1c192008-06-14 11:32:37 -07001130
Junio C Hamano1e3001a2016-10-31 10:41:41 -07001131 fd = open(name, flags | o_cloexec);
1132 if ((o_cloexec & O_CLOEXEC) && fd < 0 && errno == EINVAL) {
Lars Schneidercd66ada2016-10-24 20:02:59 +02001133 /* Try again w/o O_CLOEXEC: the kernel might not support it */
Junio C Hamano1e3001a2016-10-31 10:41:41 -07001134 o_cloexec &= ~O_CLOEXEC;
1135 fd = open(name, flags | o_cloexec);
Linus Torvalds44d1c192008-06-14 11:32:37 -07001136 }
Junio C Hamano1e3001a2016-10-31 10:41:41 -07001137
Eric Wong9fb94952017-07-15 18:55:40 +00001138#if defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
Junio C Hamano1e3001a2016-10-31 10:41:41 -07001139 {
1140 static int fd_cloexec = FD_CLOEXEC;
1141
1142 if (!o_cloexec && 0 <= fd && fd_cloexec) {
1143 /* Opened w/o O_CLOEXEC? try with fcntl(2) to add it */
Eric Wong9fb94952017-07-15 18:55:40 +00001144 int flags = fcntl(fd, F_GETFD);
1145 if (fcntl(fd, F_SETFD, flags | fd_cloexec))
Junio C Hamano1e3001a2016-10-31 10:41:41 -07001146 fd_cloexec = 0;
1147 }
1148 }
1149#endif
Junio C Hamano1b8ac5e2016-10-28 06:23:07 -07001150 return fd;
Linus Torvalds44d1c192008-06-14 11:32:37 -07001151}
1152
Jeff King771e7d52017-01-13 12:54:39 -05001153/*
Jeff King514c5fd2019-01-07 03:35:42 -05001154 * Find "oid" as a loose object in the local repository or in an alternate.
Jeff King771e7d52017-01-13 12:54:39 -05001155 * Returns 0 on success, negative on failure.
1156 *
1157 * The "path" out-parameter will give the path of the object we found (if any).
1158 * Note that it may point to static storage and is only valid until another
Jeff King514c5fd2019-01-07 03:35:42 -05001159 * call to stat_loose_object().
Jeff King771e7d52017-01-13 12:54:39 -05001160 */
Jeff King514c5fd2019-01-07 03:35:42 -05001161static int stat_loose_object(struct repository *r, const struct object_id *oid,
1162 struct stat *st, const char **path)
Jeff King052fe5e2013-07-12 02:30:48 -04001163{
Jeff King263db402018-11-12 09:48:47 -05001164 struct object_directory *odb;
Christian Couderea657732018-01-17 18:54:54 +01001165 static struct strbuf buf = STRBUF_INIT;
Jeff King052fe5e2013-07-12 02:30:48 -04001166
Stefan Bellerd2607fa2018-03-23 18:21:17 +01001167 prepare_alt_odb(r);
Jeff Kingf0eaf632018-11-12 09:50:39 -05001168 for (odb = r->objects->odb; odb; odb = odb->next) {
Jeff King514c5fd2019-01-07 03:35:42 -05001169 *path = odb_loose_path(odb, &buf, oid);
Jeff King771e7d52017-01-13 12:54:39 -05001170 if (!lstat(*path, st))
Jeff King052fe5e2013-07-12 02:30:48 -04001171 return 0;
1172 }
1173
1174 return -1;
1175}
1176
Jeff King771e7d52017-01-13 12:54:39 -05001177/*
Jeff King514c5fd2019-01-07 03:35:42 -05001178 * Like stat_loose_object(), but actually open the object and return the
Jeff King771e7d52017-01-13 12:54:39 -05001179 * descriptor. See the caveats on the "path" parameter above.
1180 */
Jeff King514c5fd2019-01-07 03:35:42 -05001181static int open_loose_object(struct repository *r,
1182 const struct object_id *oid, const char **path)
Linus Torvalds44d1c192008-06-14 11:32:37 -07001183{
1184 int fd;
Jeff King263db402018-11-12 09:48:47 -05001185 struct object_directory *odb;
Jeff Kingf0eaf632018-11-12 09:50:39 -05001186 int most_interesting_errno = ENOENT;
Christian Couderea657732018-01-17 18:54:54 +01001187 static struct strbuf buf = STRBUF_INIT;
Linus Torvalds44d1c192008-06-14 11:32:37 -07001188
Stefan Bellerec7283e2018-03-23 18:21:18 +01001189 prepare_alt_odb(r);
Jeff Kingf0eaf632018-11-12 09:50:39 -05001190 for (odb = r->objects->odb; odb; odb = odb->next) {
Jeff King514c5fd2019-01-07 03:35:42 -05001191 *path = odb_loose_path(odb, &buf, oid);
Jeff King771e7d52017-01-13 12:54:39 -05001192 fd = git_open(*path);
Linus Torvalds44d1c192008-06-14 11:32:37 -07001193 if (fd >= 0)
1194 return fd;
Jeff Kingf0eaf632018-11-12 09:50:39 -05001195
Jeff Kingd6c8a052014-05-15 04:54:06 -04001196 if (most_interesting_errno == ENOENT)
1197 most_interesting_errno = errno;
Linus Torvalds44d1c192008-06-14 11:32:37 -07001198 }
Jeff Kingd6c8a052014-05-15 04:54:06 -04001199 errno = most_interesting_errno;
Linus Torvalds44d1c192008-06-14 11:32:37 -07001200 return -1;
1201}
1202
Jeff King61c77112018-11-12 09:54:42 -05001203static int quick_has_loose(struct repository *r,
Jeff Kingd7a24572019-01-07 03:37:29 -05001204 const struct object_id *oid)
Jeff King61c77112018-11-12 09:54:42 -05001205{
Jeff King61c77112018-11-12 09:54:42 -05001206 struct object_directory *odb;
1207
Jeff King61c77112018-11-12 09:54:42 -05001208 prepare_alt_odb(r);
1209 for (odb = r->objects->odb; odb; odb = odb->next) {
Eric Wong92d8ed82021-07-07 23:10:19 +00001210 if (oidtree_contains(odb_loose_cache(odb, oid), oid))
Jeff King61c77112018-11-12 09:54:42 -05001211 return 1;
1212 }
1213 return 0;
1214}
1215
Jeff Kingf6371f92017-01-13 12:58:16 -05001216/*
Jonathan Tanae285ac2022-12-14 11:17:41 -08001217 * Map and close the given loose object fd. The path argument is used for
1218 * error reporting.
Jeff Kingf6371f92017-01-13 12:58:16 -05001219 */
Jonathan Tanae285ac2022-12-14 11:17:41 -08001220static void *map_fd(int fd, const char *path, unsigned long *size)
Linus Torvalds0fcfd162005-04-18 13:04:43 -07001221{
Jonathan Tanae285ac2022-12-14 11:17:41 -08001222 void *map = NULL;
1223 struct stat st;
Junio C Hamanoace15342005-05-07 00:38:04 -07001224
Jonathan Tanae285ac2022-12-14 11:17:41 -08001225 if (!fstat(fd, &st)) {
1226 *size = xsize_t(st.st_size);
1227 if (!*size) {
1228 /* mmap() is forbidden on empty files */
1229 error(_("object file %s is empty"), path);
1230 close(fd);
1231 return NULL;
Linus Torvalds144bde72005-04-23 11:09:32 -07001232 }
Jonathan Tanae285ac2022-12-14 11:17:41 -08001233 map = xmmap(NULL, *size, PROT_READ, MAP_PRIVATE, fd, 0);
Linus Torvalds0fcfd162005-04-18 13:04:43 -07001234 }
Jonathan Tanae285ac2022-12-14 11:17:41 -08001235 close(fd);
Linus Torvalds0fcfd162005-04-18 13:04:43 -07001236 return map;
1237}
1238
Jeff King514c5fd2019-01-07 03:35:42 -05001239void *map_loose_object(struct repository *r,
1240 const struct object_id *oid,
1241 unsigned long *size)
Jeff Kingf6371f92017-01-13 12:58:16 -05001242{
Jonathan Tanae285ac2022-12-14 11:17:41 -08001243 const char *p;
1244 int fd = open_loose_object(r, oid, &p);
1245
1246 if (fd < 0)
1247 return NULL;
1248 return map_fd(fd, p, size);
Jeff Kingf6371f92017-01-13 12:58:16 -05001249}
1250
Ævar Arnfjörð Bjarmason3b6a8db2021-10-01 11:16:49 +02001251enum unpack_loose_header_result unpack_loose_header(git_zstream *stream,
1252 unsigned char *map,
1253 unsigned long mapsize,
1254 void *buffer,
1255 unsigned long bufsiz,
1256 struct strbuf *header)
Linus Torvaldsc4483572005-06-01 17:54:59 -07001257{
Ævar Arnfjörð Bjarmason01cab972021-10-01 11:16:48 +02001258 int status;
Matheus Tavares31877c92020-01-15 23:39:53 -03001259
Linus Torvaldsc4483572005-06-01 17:54:59 -07001260 /* Get the data stream */
1261 memset(stream, 0, sizeof(*stream));
1262 stream->next_in = map;
1263 stream->avail_in = mapsize;
1264 stream->next_out = buffer;
Linus Torvalds93821bd2006-07-11 12:48:08 -07001265 stream->avail_out = bufsiz;
Linus Torvaldsc4483572005-06-01 17:54:59 -07001266
Linus Torvalds39c68542009-01-07 19:54:47 -08001267 git_inflate_init(stream);
Matheus Tavares31877c92020-01-15 23:39:53 -03001268 obj_read_unlock();
Ævar Arnfjörð Bjarmason01cab972021-10-01 11:16:48 +02001269 status = git_inflate(stream, 0);
Matheus Tavares31877c92020-01-15 23:39:53 -03001270 obj_read_lock();
Junio C Hamanod21f8422016-09-25 21:29:04 -07001271 if (status < Z_OK)
Ævar Arnfjörð Bjarmason3b6a8db2021-10-01 11:16:49 +02001272 return ULHR_BAD;
Karthik Nayak46f03442015-05-03 19:59:59 +05301273
1274 /*
1275 * Check if entire header is unpacked in the first iteration.
1276 */
1277 if (memchr(buffer, '\0', stream->next_out - (unsigned char *)buffer))
Ævar Arnfjörð Bjarmason3b6a8db2021-10-01 11:16:49 +02001278 return ULHR_OK;
Karthik Nayak46f03442015-05-03 19:59:59 +05301279
1280 /*
Ævar Arnfjörð Bjarmason01cab972021-10-01 11:16:48 +02001281 * We have a header longer than MAX_HEADER_LEN. The "header"
1282 * here is only non-NULL when we run "cat-file
1283 * --allow-unknown-type".
1284 */
1285 if (!header)
Ævar Arnfjörð Bjarmason5848fb12021-10-01 11:16:50 +02001286 return ULHR_TOO_LONG;
Karthik Nayak46f03442015-05-03 19:59:59 +05301287
1288 /*
1289 * buffer[0..bufsiz] was not large enough. Copy the partial
1290 * result out to header, and then append the result of further
1291 * reading the stream.
1292 */
1293 strbuf_add(header, buffer, stream->next_out - (unsigned char *)buffer);
1294 stream->next_out = buffer;
1295 stream->avail_out = bufsiz;
1296
1297 do {
Matheus Tavares31877c92020-01-15 23:39:53 -03001298 obj_read_unlock();
Karthik Nayak46f03442015-05-03 19:59:59 +05301299 status = git_inflate(stream, 0);
Matheus Tavares31877c92020-01-15 23:39:53 -03001300 obj_read_lock();
Karthik Nayak46f03442015-05-03 19:59:59 +05301301 strbuf_add(header, buffer, stream->next_out - (unsigned char *)buffer);
1302 if (memchr(buffer, '\0', stream->next_out - (unsigned char *)buffer))
1303 return 0;
1304 stream->next_out = buffer;
1305 stream->avail_out = bufsiz;
1306 } while (status != Z_STREAM_END);
Ævar Arnfjörð Bjarmason5848fb12021-10-01 11:16:50 +02001307 return ULHR_TOO_LONG;
Karthik Nayak46f03442015-05-03 19:59:59 +05301308}
1309
Jeff King00a77602019-01-07 03:37:02 -05001310static void *unpack_loose_rest(git_zstream *stream,
1311 void *buffer, unsigned long size,
1312 const struct object_id *oid)
Linus Torvalds0fcfd162005-04-18 13:04:43 -07001313{
Linus Torvalds5180cac2005-06-02 07:57:25 -07001314 int bytes = strlen(buffer) + 1;
Ilari Liusvaara3aee68a2010-01-26 20:24:14 +02001315 unsigned char *buf = xmallocz(size);
Linus Torvalds93821bd2006-07-11 12:48:08 -07001316 unsigned long n;
Junio C Hamano7efbff72007-03-05 00:21:37 -08001317 int status = Z_OK;
Linus Torvalds0fcfd162005-04-18 13:04:43 -07001318
Linus Torvalds93821bd2006-07-11 12:48:08 -07001319 n = stream->total_out - bytes;
1320 if (n > size)
1321 n = size;
1322 memcpy(buf, (char *) buffer + bytes, n);
1323 bytes = n;
Linus Torvalds456cdf62007-03-19 22:49:53 -07001324 if (bytes <= size) {
1325 /*
1326 * The above condition must be (bytes <= size), not
1327 * (bytes < size). In other words, even though we
Junio C Hamanoccf5ace2011-05-15 12:16:03 -07001328 * expect no more output and set avail_out to zero,
Linus Torvalds456cdf62007-03-19 22:49:53 -07001329 * the input zlib stream may have bytes that express
1330 * "this concludes the stream", and we *do* want to
1331 * eat that input.
1332 *
1333 * Otherwise we would not be able to test that we
1334 * consumed all the input to reach the expected size;
1335 * we also want to check that zlib tells us that all
1336 * went well with status == Z_STREAM_END at the end.
1337 */
Linus Torvalds5180cac2005-06-02 07:57:25 -07001338 stream->next_out = buf + bytes;
1339 stream->avail_out = size - bytes;
Matheus Tavares31877c92020-01-15 23:39:53 -03001340 while (status == Z_OK) {
1341 obj_read_unlock();
Linus Torvalds39c68542009-01-07 19:54:47 -08001342 status = git_inflate(stream, Z_FINISH);
Matheus Tavares31877c92020-01-15 23:39:53 -03001343 obj_read_lock();
1344 }
Linus Torvalds0fcfd162005-04-18 13:04:43 -07001345 }
Linus Torvalds456cdf62007-03-19 22:49:53 -07001346 if (status == Z_STREAM_END && !stream->avail_in) {
Linus Torvalds39c68542009-01-07 19:54:47 -08001347 git_inflate_end(stream);
Junio C Hamano7efbff72007-03-05 00:21:37 -08001348 return buf;
1349 }
1350
1351 if (status < 0)
Jeff King00a77602019-01-07 03:37:02 -05001352 error(_("corrupt loose object '%s'"), oid_to_hex(oid));
Junio C Hamano7efbff72007-03-05 00:21:37 -08001353 else if (stream->avail_in)
Nguyễn Thái Ngọc Duy259328b2018-07-21 09:49:39 +02001354 error(_("garbage at end of loose object '%s'"),
Jeff King00a77602019-01-07 03:37:02 -05001355 oid_to_hex(oid));
Junio C Hamano7efbff72007-03-05 00:21:37 -08001356 free(buf);
1357 return NULL;
Linus Torvalds0fcfd162005-04-18 13:04:43 -07001358}
1359
Linus Torvalds5180cac2005-06-02 07:57:25 -07001360/*
1361 * We used to just use "sscanf()", but that's actually way
1362 * too permissive for what we want to check. So do an anal
1363 * object header parse by hand.
1364 */
Ævar Arnfjörð Bjarmasondccb32b2021-10-01 11:16:51 +02001365int parse_loose_header(const char *hdr, struct object_info *oi)
Linus Torvalds5180cac2005-06-02 07:57:25 -07001366{
Karthik Nayak46f03442015-05-03 19:59:59 +05301367 const char *type_buf = hdr;
Matt Cooperd6a09e72021-11-02 15:46:10 +00001368 size_t size;
Karthik Nayak46f03442015-05-03 19:59:59 +05301369 int type, type_len = 0;
Linus Torvalds5180cac2005-06-02 07:57:25 -07001370
1371 /*
Karthik Nayak46f03442015-05-03 19:59:59 +05301372 * The type can be of any size but is followed by
Nicolas Pitre21666f12007-02-26 14:55:59 -05001373 * a space.
Linus Torvalds5180cac2005-06-02 07:57:25 -07001374 */
Linus Torvalds5180cac2005-06-02 07:57:25 -07001375 for (;;) {
1376 char c = *hdr++;
Junio C Hamanod21f8422016-09-25 21:29:04 -07001377 if (!c)
1378 return -1;
Linus Torvalds5180cac2005-06-02 07:57:25 -07001379 if (c == ' ')
1380 break;
Karthik Nayak46f03442015-05-03 19:59:59 +05301381 type_len++;
Linus Torvalds5180cac2005-06-02 07:57:25 -07001382 }
Karthik Nayak46f03442015-05-03 19:59:59 +05301383
1384 type = type_from_string_gently(type_buf, type_len, 1);
Brandon Williams6ca32f42018-02-14 10:59:23 -08001385 if (oi->type_name)
1386 strbuf_add(oi->type_name, type_buf, type_len);
Karthik Nayak46f03442015-05-03 19:59:59 +05301387 if (oi->typep)
1388 *oi->typep = type;
Linus Torvalds5180cac2005-06-02 07:57:25 -07001389
1390 /*
1391 * The length must follow immediately, and be in canonical
1392 * decimal format (ie "010" is not valid).
1393 */
1394 size = *hdr++ - '0';
1395 if (size > 9)
1396 return -1;
1397 if (size) {
1398 for (;;) {
1399 unsigned long c = *hdr - '0';
1400 if (c > 9)
1401 break;
1402 hdr++;
Matt Cooperd6a09e72021-11-02 15:46:10 +00001403 size = st_add(st_mult(size, 10), c);
Linus Torvalds5180cac2005-06-02 07:57:25 -07001404 }
1405 }
Karthik Nayak46f03442015-05-03 19:59:59 +05301406
1407 if (oi->sizep)
Matt Cooperd6a09e72021-11-02 15:46:10 +00001408 *oi->sizep = cast_size_t_to_ulong(size);
Linus Torvalds5180cac2005-06-02 07:57:25 -07001409
1410 /*
1411 * The length must be followed by a zero byte
1412 */
Ævar Arnfjörð Bjarmasondccb32b2021-10-01 11:16:51 +02001413 if (*hdr)
1414 return -1;
Karthik Nayak46f03442015-05-03 19:59:59 +05301415
Ævar Arnfjörð Bjarmasondccb32b2021-10-01 11:16:51 +02001416 /*
1417 * The format is valid, but the type may still be bogus. The
1418 * Caller needs to check its oi->typep.
1419 */
1420 return 0;
Linus Torvalds5180cac2005-06-02 07:57:25 -07001421}
1422
Jeff King514c5fd2019-01-07 03:35:42 -05001423static int loose_object_info(struct repository *r,
1424 const struct object_id *oid,
1425 struct object_info *oi, int flags)
Junio C Hamano65c2e0c2005-06-02 15:20:54 -07001426{
Karthik Nayak46f03442015-05-03 19:59:59 +05301427 int status = 0;
Jonathan Tan9e59b382022-12-14 11:17:42 -08001428 int fd;
Karthik Nayak46f03442015-05-03 19:59:59 +05301429 unsigned long mapsize;
Jonathan Tan9e59b382022-12-14 11:17:42 -08001430 const char *path;
Junio C Hamano65c2e0c2005-06-02 15:20:54 -07001431 void *map;
Junio C Hamanoef49a7a2011-06-10 11:52:15 -07001432 git_zstream stream;
brian m. carlson1af64f72018-03-12 02:27:55 +00001433 char hdr[MAX_HEADER_LEN];
Karthik Nayak46f03442015-05-03 19:59:59 +05301434 struct strbuf hdrbuf = STRBUF_INIT;
Jonathan Tanc84a1f32017-06-21 17:40:21 -07001435 unsigned long size_scratch;
Ævar Arnfjörð Bjarmasondccb32b2021-10-01 11:16:51 +02001436 enum object_type type_scratch;
Ævar Arnfjörð Bjarmason01cab972021-10-01 11:16:48 +02001437 int allow_unknown = flags & OBJECT_INFO_ALLOW_UNKNOWN_TYPE;
Junio C Hamano65c2e0c2005-06-02 15:20:54 -07001438
Jeff Kingb99b6bc2020-02-23 23:36:56 -05001439 if (oi->delta_base_oid)
1440 oidclr(oi->delta_base_oid);
Jeff King5d642e72013-12-21 09:24:20 -05001441
Jeff King052fe5e2013-07-12 02:30:48 -04001442 /*
1443 * If we don't care about type or size, then we don't
Junio C Hamano4ef8d1d2013-11-06 10:00:57 -08001444 * need to look inside the object at all. Note that we
1445 * do not optimize out the stat call, even if the
1446 * caller doesn't care about the disk-size, since our
1447 * return value implicitly indicates whether the
1448 * object even exists.
Jeff King052fe5e2013-07-12 02:30:48 -04001449 */
Brandon Williams6ca32f42018-02-14 10:59:23 -08001450 if (!oi->typep && !oi->type_name && !oi->sizep && !oi->contentp) {
Junio C Hamano4ef8d1d2013-11-06 10:00:57 -08001451 struct stat st;
Jeff King61c77112018-11-12 09:54:42 -05001452 if (!oi->disk_sizep && (flags & OBJECT_INFO_QUICK))
Jeff Kingd7a24572019-01-07 03:37:29 -05001453 return quick_has_loose(r, oid) ? 0 : -1;
Jeff King514c5fd2019-01-07 03:35:42 -05001454 if (stat_loose_object(r, oid, &st, &path) < 0)
Junio C Hamano4ef8d1d2013-11-06 10:00:57 -08001455 return -1;
1456 if (oi->disk_sizep)
Jeff King23c339c2013-07-12 02:37:53 -04001457 *oi->disk_sizep = st.st_size;
Jeff King052fe5e2013-07-12 02:30:48 -04001458 return 0;
1459 }
1460
Jonathan Tan9e59b382022-12-14 11:17:42 -08001461 fd = open_loose_object(r, oid, &path);
1462 if (fd < 0) {
1463 if (errno != ENOENT)
1464 error_errno(_("unable to open loose object %s"), oid_to_hex(oid));
1465 return -1;
1466 }
1467 map = map_fd(fd, path, &mapsize);
Johannes Schindelinf0df4ed2006-11-28 00:18:55 +01001468 if (!map)
Thomas Rastdbea72a2013-05-30 22:00:22 +02001469 return -1;
Jonathan Tanc84a1f32017-06-21 17:40:21 -07001470
1471 if (!oi->sizep)
1472 oi->sizep = &size_scratch;
Ævar Arnfjörð Bjarmasondccb32b2021-10-01 11:16:51 +02001473 if (!oi->typep)
1474 oi->typep = &type_scratch;
Jonathan Tanc84a1f32017-06-21 17:40:21 -07001475
Jeff King23c339c2013-07-12 02:37:53 -04001476 if (oi->disk_sizep)
1477 *oi->disk_sizep = mapsize;
Ævar Arnfjörð Bjarmason01cab972021-10-01 11:16:48 +02001478
Ævar Arnfjörð Bjarmason3b6a8db2021-10-01 11:16:49 +02001479 switch (unpack_loose_header(&stream, map, mapsize, hdr, sizeof(hdr),
1480 allow_unknown ? &hdrbuf : NULL)) {
1481 case ULHR_OK:
Ævar Arnfjörð Bjarmasondccb32b2021-10-01 11:16:51 +02001482 if (parse_loose_header(hdrbuf.len ? hdrbuf.buf : hdr, oi) < 0)
1483 status = error(_("unable to parse %s header"), oid_to_hex(oid));
1484 else if (!allow_unknown && *oi->typep < 0)
1485 die(_("invalid object type"));
1486
1487 if (!oi->contentp)
1488 break;
1489 *oi->contentp = unpack_loose_rest(&stream, hdr, *oi->sizep, oid);
1490 if (*oi->contentp)
1491 goto cleanup;
1492
1493 status = -1;
Ævar Arnfjörð Bjarmason3b6a8db2021-10-01 11:16:49 +02001494 break;
1495 case ULHR_BAD:
Nguyễn Thái Ngọc Duy259328b2018-07-21 09:49:39 +02001496 status = error(_("unable to unpack %s header"),
Jeff King514c5fd2019-01-07 03:35:42 -05001497 oid_to_hex(oid));
Ævar Arnfjörð Bjarmason3b6a8db2021-10-01 11:16:49 +02001498 break;
Ævar Arnfjörð Bjarmason5848fb12021-10-01 11:16:50 +02001499 case ULHR_TOO_LONG:
1500 status = error(_("header for %s too long, exceeds %d bytes"),
1501 oid_to_hex(oid), MAX_HEADER_LEN);
1502 break;
Ævar Arnfjörð Bjarmason3b6a8db2021-10-01 11:16:49 +02001503 }
Jonathan Tanc84a1f32017-06-21 17:40:21 -07001504
Jonathan Tan9e59b382022-12-14 11:17:42 -08001505 if (status && (flags & OBJECT_INFO_DIE_IF_CORRUPT))
1506 die(_("loose object %s (stored in %s) is corrupt"),
1507 oid_to_hex(oid), path);
1508
Ævar Arnfjörð Bjarmasondccb32b2021-10-01 11:16:51 +02001509 git_inflate_end(&stream);
1510cleanup:
Junio C Hamano65c2e0c2005-06-02 15:20:54 -07001511 munmap(map, mapsize);
Jonathan Tanc84a1f32017-06-21 17:40:21 -07001512 if (oi->sizep == &size_scratch)
1513 oi->sizep = NULL;
Karthik Nayak46f03442015-05-03 19:59:59 +05301514 strbuf_release(&hdrbuf);
Ævar Arnfjörð Bjarmasondccb32b2021-10-01 11:16:51 +02001515 if (oi->typep == &type_scratch)
1516 oi->typep = NULL;
Jonathan Tan3ab0fb02017-08-11 13:36:14 -07001517 oi->whence = OI_LOOSE;
Ævar Arnfjörð Bjarmasondccb32b2021-10-01 11:16:51 +02001518 return status;
Junio C Hamano65c2e0c2005-06-02 15:20:54 -07001519}
1520
Matheus Tavares31877c92020-01-15 23:39:53 -03001521int obj_read_use_lock = 0;
1522pthread_mutex_t obj_read_mutex;
1523
1524void enable_obj_read_lock(void)
1525{
1526 if (obj_read_use_lock)
1527 return;
1528
1529 obj_read_use_lock = 1;
1530 init_recursive_mutex(&obj_read_mutex);
1531}
1532
1533void disable_obj_read_lock(void)
1534{
1535 if (!obj_read_use_lock)
1536 return;
1537
1538 obj_read_use_lock = 0;
1539 pthread_mutex_destroy(&obj_read_mutex);
1540}
1541
Jonathan Tan8b4c0102017-12-08 15:27:14 +00001542int fetch_if_missing = 1;
1543
Matheus Tavares31877c92020-01-15 23:39:53 -03001544static int do_oid_object_info_extended(struct repository *r,
1545 const struct object_id *oid,
1546 struct object_info *oi, unsigned flags)
Johannes Schindelinf0df4ed2006-11-28 00:18:55 +01001547{
Jonathan Tancd585e22017-06-21 17:40:23 -07001548 static struct object_info blank_oi = OBJECT_INFO_INIT;
Jonathan Tan9c8a2942020-01-02 12:16:30 -08001549 struct cached_object *co;
Johannes Schindelinf0df4ed2006-11-28 00:18:55 +01001550 struct pack_entry e;
Jeff King5b086402013-07-12 02:34:57 -04001551 int rtype;
brian m. carlsonb383a132018-03-12 02:27:54 +00001552 const struct object_id *real = oid;
Jonathan Tan8b4c0102017-12-08 15:27:14 +00001553 int already_retried = 0;
Johannes Schindelinf0df4ed2006-11-28 00:18:55 +01001554
Matheus Tavares31877c92020-01-15 23:39:53 -03001555
brian m. carlsonb383a132018-03-12 02:27:54 +00001556 if (flags & OBJECT_INFO_LOOKUP_REPLACE)
Stefan Beller9d983542018-04-25 11:21:06 -07001557 real = lookup_replace_object(r, oid);
Johannes Schindelinf0df4ed2006-11-28 00:18:55 +01001558
brian m. carlsonb383a132018-03-12 02:27:54 +00001559 if (is_null_oid(real))
Jeff King87b5e232017-11-21 18:17:39 -05001560 return -1;
1561
Jonathan Tancd585e22017-06-21 17:40:23 -07001562 if (!oi)
1563 oi = &blank_oi;
1564
Jonathan Tan9c8a2942020-01-02 12:16:30 -08001565 co = find_cached_object(real);
1566 if (co) {
1567 if (oi->typep)
1568 *(oi->typep) = co->type;
1569 if (oi->sizep)
1570 *(oi->sizep) = co->size;
1571 if (oi->disk_sizep)
1572 *(oi->disk_sizep) = 0;
Jeff Kingb99b6bc2020-02-23 23:36:56 -05001573 if (oi->delta_base_oid)
1574 oidclr(oi->delta_base_oid);
Jonathan Tan9c8a2942020-01-02 12:16:30 -08001575 if (oi->type_name)
1576 strbuf_addstr(oi->type_name, type_name(co->type));
1577 if (oi->contentp)
1578 *oi->contentp = xmemdupz(co->buf, co->size);
1579 oi->whence = OI_CACHED;
1580 return 0;
Nguyễn Thái Ngọc Duyc4d99862011-02-05 21:03:02 +07001581 }
1582
Jonathan Tan8b4c0102017-12-08 15:27:14 +00001583 while (1) {
Junio C Hamano42c8ce12018-05-30 14:04:10 +09001584 if (find_pack_entry(r, real, &e))
Jonathan Tan8b4c0102017-12-08 15:27:14 +00001585 break;
1586
Steven Grimmddd63e62008-08-05 13:08:41 -07001587 /* Most likely it's a loose object. */
Jeff King514c5fd2019-01-07 03:35:42 -05001588 if (!loose_object_info(r, real, oi, flags))
Jeff King5b086402013-07-12 02:34:57 -04001589 return 0;
Steven Grimmddd63e62008-08-05 13:08:41 -07001590
1591 /* Not a loose object; someone else may have just packed it. */
Jonathan Tan2b7750c2018-03-13 08:30:29 -07001592 if (!(flags & OBJECT_INFO_QUICK)) {
Stefan Beller9d983542018-04-25 11:21:06 -07001593 reprepare_packed_git(r);
Junio C Hamano42c8ce12018-05-30 14:04:10 +09001594 if (find_pack_entry(r, real, &e))
Jonathan Tan2b7750c2018-03-13 08:30:29 -07001595 break;
1596 }
Jonathan Tan8b4c0102017-12-08 15:27:14 +00001597
Jonathan Taneef71902021-10-08 14:08:18 -07001598 /*
1599 * If r is the_repository, this might be an attempt at
1600 * accessing a submodule object as if it were in the_repository
1601 * (having called add_submodule_odb() on that submodule's ODB).
1602 * If any such ODBs exist, register them and try again.
1603 */
1604 if (r == the_repository &&
1605 register_all_submodule_odb_as_alternates())
Jonathan Tana35e03d2021-08-16 14:09:51 -07001606 /* We added some alternates; retry */
1607 continue;
1608
Jonathan Tan8b4c0102017-12-08 15:27:14 +00001609 /* Check if it is a missing object */
Jonathan Tanef830cc2021-06-17 10:13:26 -07001610 if (fetch_if_missing && repo_has_promisor_remote(r) &&
1611 !already_retried &&
Derrick Stolee31f52562019-05-28 08:19:07 -07001612 !(flags & OBJECT_INFO_SKIP_FETCH_OBJECT)) {
Christian Couderb14ed5a2019-06-25 15:40:31 +02001613 promisor_remote_get_direct(r, real, 1);
Jonathan Tan8b4c0102017-12-08 15:27:14 +00001614 already_retried = 1;
1615 continue;
Jonathan Tandfdd4af2017-06-21 17:40:22 -07001616 }
Jonathan Tan8b4c0102017-12-08 15:27:14 +00001617
Jonathan Tan9e59b382022-12-14 11:17:42 -08001618 if (flags & OBJECT_INFO_DIE_IF_CORRUPT) {
1619 const struct packed_git *p;
1620 if ((flags & OBJECT_INFO_LOOKUP_REPLACE) && !oideq(real, oid))
1621 die(_("replacement %s not found for %s"),
1622 oid_to_hex(real), oid_to_hex(oid));
1623 if ((p = has_packed_and_bad(r, real)))
1624 die(_("packed object %s (stored in %s) is corrupt"),
1625 oid_to_hex(real), p->pack_name);
1626 }
Jonathan Tan8b4c0102017-12-08 15:27:14 +00001627 return -1;
Johannes Schindelinf0df4ed2006-11-28 00:18:55 +01001628 }
Nicolas Pitre3d77d872008-10-29 19:02:47 -04001629
Jonathan Tancd585e22017-06-21 17:40:23 -07001630 if (oi == &blank_oi)
1631 /*
1632 * We know that the caller doesn't actually need the
1633 * information below, so return early.
1634 */
1635 return 0;
Stefan Beller9d983542018-04-25 11:21:06 -07001636 rtype = packed_object_info(r, e.p, e.offset, oi);
Jeff King412916e2013-07-12 02:32:25 -04001637 if (rtype < 0) {
René Scharfe751530d2021-09-11 22:40:33 +02001638 mark_bad_packed_object(e.p, real);
Matheus Tavares31877c92020-01-15 23:39:53 -03001639 return do_oid_object_info_extended(r, real, oi, 0);
Jonathan Tan3ab0fb02017-08-11 13:36:14 -07001640 } else if (oi->whence == OI_PACKED) {
Junio C Hamano9a490592011-05-12 15:51:38 -07001641 oi->u.packed.offset = e.offset;
1642 oi->u.packed.pack = e.p;
1643 oi->u.packed.is_delta = (rtype == OBJ_REF_DELTA ||
1644 rtype == OBJ_OFS_DELTA);
Nicolas Pitre3d77d872008-10-29 19:02:47 -04001645 }
1646
Jeff King5b086402013-07-12 02:34:57 -04001647 return 0;
Johannes Schindelinf0df4ed2006-11-28 00:18:55 +01001648}
1649
Matheus Tavares31877c92020-01-15 23:39:53 -03001650int oid_object_info_extended(struct repository *r, const struct object_id *oid,
1651 struct object_info *oi, unsigned flags)
1652{
1653 int ret;
1654 obj_read_lock();
1655 ret = do_oid_object_info_extended(r, oid, oi, flags);
1656 obj_read_unlock();
1657 return ret;
1658}
1659
1660
Christian Couder3fc0dca2013-10-27 00:34:30 +02001661/* returns enum object_type or negative */
Stefan Beller9d983542018-04-25 11:21:06 -07001662int oid_object_info(struct repository *r,
1663 const struct object_id *oid,
1664 unsigned long *sizep)
Junio C Hamano9a490592011-05-12 15:51:38 -07001665{
Jeff King5b086402013-07-12 02:34:57 -04001666 enum object_type type;
Jeff King27b5c1a2016-08-11 05:24:35 -04001667 struct object_info oi = OBJECT_INFO_INIT;
Junio C Hamano9a490592011-05-12 15:51:38 -07001668
Jeff King5b086402013-07-12 02:34:57 -04001669 oi.typep = &type;
Junio C Hamano9a490592011-05-12 15:51:38 -07001670 oi.sizep = sizep;
Stefan Beller9d983542018-04-25 11:21:06 -07001671 if (oid_object_info_extended(r, oid, &oi,
1672 OBJECT_INFO_LOOKUP_REPLACE) < 0)
Jeff King5b086402013-07-12 02:34:57 -04001673 return -1;
1674 return type;
Junio C Hamano9a490592011-05-12 15:51:38 -07001675}
1676
Patryk Obara829e5c32018-01-28 01:13:11 +01001677int pretend_object_file(void *buf, unsigned long len, enum object_type type,
1678 struct object_id *oid)
Junio C Hamanod66b37b2007-02-04 21:42:38 -08001679{
1680 struct cached_object *co;
1681
Ævar Arnfjörð Bjarmason44439c12022-02-05 00:48:32 +01001682 hash_object_file(the_hash_algo, buf, len, type, oid);
Jonathan Tana64d2aa2020-07-21 15:50:20 -07001683 if (has_object_file_with_flags(oid, OBJECT_INFO_QUICK | OBJECT_INFO_SKIP_FETCH_OBJECT) ||
1684 find_cached_object(oid))
Junio C Hamanod66b37b2007-02-04 21:42:38 -08001685 return 0;
Dmitry S. Dolzhenkoc7353962014-03-04 02:32:02 +04001686 ALLOC_GROW(cached_objects, cached_object_nr + 1, cached_object_alloc);
Junio C Hamanod66b37b2007-02-04 21:42:38 -08001687 co = &cached_objects[cached_object_nr++];
1688 co->size = len;
Nicolas Pitre21666f12007-02-26 14:55:59 -05001689 co->type = type;
Junio C Hamanoefa13f72007-02-15 17:02:06 -08001690 co->buf = xmalloc(len);
1691 memcpy(co->buf, buf, len);
brian m. carlson62ba93e2018-05-02 00:26:03 +00001692 oidcpy(&co->oid, oid);
Junio C Hamanod66b37b2007-02-04 21:42:38 -08001693 return 0;
1694}
1695
Junio C Hamanob6c4cec2010-10-28 11:13:06 -07001696/*
1697 * This function dies on corrupt objects; the callers who want to
Jeff Kingb25562e2023-01-07 08:48:55 -05001698 * deal with them should arrange to call oid_object_info_extended() and give
1699 * error messages themselves.
Junio C Hamanob6c4cec2010-10-28 11:13:06 -07001700 */
Jeff King0ba05cf2023-01-07 08:50:33 -05001701void *repo_read_object_file(struct repository *r,
1702 const struct object_id *oid,
1703 enum object_type *type,
1704 unsigned long *size)
Nicolas Pitreac939102008-07-14 21:46:48 -04001705{
Jeff Kingb25562e2023-01-07 08:48:55 -05001706 struct object_info oi = OBJECT_INFO_INIT;
Jeff King7be13f52023-01-07 08:50:19 -05001707 unsigned flags = OBJECT_INFO_DIE_IF_CORRUPT | OBJECT_INFO_LOOKUP_REPLACE;
Junio C Hamano3ba7a062010-10-28 11:13:06 -07001708 void *data;
Junio C Hamanob6c4cec2010-10-28 11:13:06 -07001709
Jeff Kingb25562e2023-01-07 08:48:55 -05001710 oi.typep = type;
1711 oi.sizep = size;
1712 oi.contentp = &data;
Jeff Kingb25562e2023-01-07 08:48:55 -05001713 if (oid_object_info_extended(r, oid, &oi, flags))
Jeff King15b63682023-01-12 11:06:49 -05001714 return NULL;
Christian Couder68095572009-01-23 10:06:53 +01001715
Jeff Kingb25562e2023-01-07 08:48:55 -05001716 return data;
Nicolas Pitreac939102008-07-14 21:46:48 -04001717}
1718
Nguyễn Thái Ngọc Duyd3b47052019-06-27 16:28:47 +07001719void *read_object_with_reference(struct repository *r,
1720 const struct object_id *oid,
Ævar Arnfjörð Bjarmason6aea6ba2022-02-05 00:48:34 +01001721 enum object_type required_type,
Junio C Hamano40469ee2005-04-28 16:42:27 -07001722 unsigned long *size,
brian m. carlson02f05472018-03-12 02:27:52 +00001723 struct object_id *actual_oid_return)
Junio C Hamanof4913f92005-04-20 18:06:49 -07001724{
Ævar Arnfjörð Bjarmason6aea6ba2022-02-05 00:48:34 +01001725 enum object_type type;
Junio C Hamanof4913f92005-04-20 18:06:49 -07001726 void *buffer;
1727 unsigned long isize;
brian m. carlson02f05472018-03-12 02:27:52 +00001728 struct object_id actual_oid;
Junio C Hamanof4913f92005-04-20 18:06:49 -07001729
brian m. carlson02f05472018-03-12 02:27:52 +00001730 oidcpy(&actual_oid, oid);
Junio C Hamano40469ee2005-04-28 16:42:27 -07001731 while (1) {
1732 int ref_length = -1;
1733 const char *ref_type = NULL;
Junio C Hamanof4913f92005-04-20 18:06:49 -07001734
Nguyễn Thái Ngọc Duyd3b47052019-06-27 16:28:47 +07001735 buffer = repo_read_object_file(r, &actual_oid, &type, &isize);
Junio C Hamano40469ee2005-04-28 16:42:27 -07001736 if (!buffer)
1737 return NULL;
Nicolas Pitre21666f12007-02-26 14:55:59 -05001738 if (type == required_type) {
Junio C Hamano40469ee2005-04-28 16:42:27 -07001739 *size = isize;
brian m. carlson02f05472018-03-12 02:27:52 +00001740 if (actual_oid_return)
1741 oidcpy(actual_oid_return, &actual_oid);
Junio C Hamano40469ee2005-04-28 16:42:27 -07001742 return buffer;
1743 }
1744 /* Handle references */
Nicolas Pitre21666f12007-02-26 14:55:59 -05001745 else if (type == OBJ_COMMIT)
Junio C Hamano40469ee2005-04-28 16:42:27 -07001746 ref_type = "tree ";
Nicolas Pitre21666f12007-02-26 14:55:59 -05001747 else if (type == OBJ_TAG)
Junio C Hamano40469ee2005-04-28 16:42:27 -07001748 ref_type = "object ";
1749 else {
1750 free(buffer);
1751 return NULL;
1752 }
1753 ref_length = strlen(ref_type);
1754
brian m. carlson94b5e092018-07-16 01:28:07 +00001755 if (ref_length + the_hash_algo->hexsz > isize ||
Martin Koegler50974ec2008-02-18 21:47:52 +01001756 memcmp(buffer, ref_type, ref_length) ||
brian m. carlson02f05472018-03-12 02:27:52 +00001757 get_oid_hex((char *) buffer + ref_length, &actual_oid)) {
Junio C Hamano40469ee2005-04-28 16:42:27 -07001758 free(buffer);
1759 return NULL;
1760 }
Sergey Vlasov1cf58e72005-08-08 22:44:43 +04001761 free(buffer);
Junio C Hamano40469ee2005-04-28 16:42:27 -07001762 /* Now we have the ID of the referred-to object in
brian m. carlson02f05472018-03-12 02:27:52 +00001763 * actual_oid. Check again. */
Junio C Hamanof4913f92005-04-20 18:06:49 -07001764 }
Junio C Hamanof4913f92005-04-20 18:06:49 -07001765}
1766
Ævar Arnfjörð Bjarmason2bbb28a2022-02-05 00:48:33 +01001767static void hash_object_body(const struct git_hash_algo *algo, git_hash_ctx *c,
1768 const void *buf, unsigned long len,
1769 struct object_id *oid,
1770 char *hdr, int *hdrlen)
1771{
1772 algo->init_fn(c);
1773 algo->update_fn(c, hdr, *hdrlen);
1774 algo->update_fn(c, buf, len);
1775 algo->final_oid_fn(oid, c);
1776}
1777
Matheus Tavares7ad5c442020-01-30 17:32:21 -03001778static void write_object_file_prepare(const struct git_hash_algo *algo,
1779 const void *buf, unsigned long len,
Ævar Arnfjörð Bjarmason2bbb28a2022-02-05 00:48:33 +01001780 enum object_type type, struct object_id *oid,
1781 char *hdr, int *hdrlen)
1782{
1783 git_hash_ctx c;
1784
1785 /* Generate the header */
1786 *hdrlen = format_object_header(hdr, *hdrlen, type, len);
1787
1788 /* Sha1.. */
1789 hash_object_body(algo, &c, buf, len, oid, hdr, hdrlen);
1790}
1791
1792static void write_object_file_prepare_literally(const struct git_hash_algo *algo,
1793 const void *buf, unsigned long len,
Patryk Obaraa09c9852018-01-28 01:13:19 +01001794 const char *type, struct object_id *oid,
1795 char *hdr, int *hdrlen)
Junio C Hamanod410c0f2005-06-27 19:03:13 -07001796{
brian m. carlson18e25882018-02-01 02:18:41 +00001797 git_hash_ctx c;
Junio C Hamanod410c0f2005-06-27 19:03:13 -07001798
Ævar Arnfjörð Bjarmasonb04cdea2022-02-05 00:48:25 +01001799 *hdrlen = format_object_header_literally(hdr, *hdrlen, type, len);
Ævar Arnfjörð Bjarmason2bbb28a2022-02-05 00:48:33 +01001800 hash_object_body(algo, &c, buf, len, oid, hdr, hdrlen);
Junio C Hamanod410c0f2005-06-27 19:03:13 -07001801}
1802
Linus Torvalds230f1322005-10-08 15:54:01 -07001803/*
Junio C Hamano5a688fe2009-03-25 16:19:36 -07001804 * Move the just written object into its final resting place.
Linus Torvalds230f1322005-10-08 15:54:01 -07001805 */
Junio C Hamanocb5add52015-08-07 14:40:24 -07001806int finalize_object_file(const char *tmpfile, const char *filename)
Linus Torvalds230f1322005-10-08 15:54:01 -07001807{
Thomas Raste32c0a92008-09-19 00:24:46 +02001808 int ret = 0;
Junio C Hamano5a688fe2009-03-25 16:19:36 -07001809
Johannes Schindelin348df162009-04-28 00:32:25 +02001810 if (object_creation_mode == OBJECT_CREATION_USES_RENAMES)
Johannes Schindelinbe66a6c2009-04-25 11:57:14 +02001811 goto try_rename;
1812 else if (link(tmpfile, filename))
Thomas Raste32c0a92008-09-19 00:24:46 +02001813 ret = errno;
Linus Torvalds7ebb6fc2005-10-26 10:27:36 -07001814
1815 /*
1816 * Coda hack - coda doesn't like cross-directory links,
1817 * so we fall back to a rename, which will mean that it
1818 * won't be able to check collisions, but that's not a
1819 * big deal.
1820 *
1821 * The same holds for FAT formatted media.
1822 *
Junio C Hamano3be1f182009-03-27 23:14:39 -07001823 * When this succeeds, we just return. We have nothing
Linus Torvalds7ebb6fc2005-10-26 10:27:36 -07001824 * left to unlink.
1825 */
1826 if (ret && ret != EEXIST) {
Johannes Schindelinbe66a6c2009-04-25 11:57:14 +02001827 try_rename:
Linus Torvalds7ebb6fc2005-10-26 10:27:36 -07001828 if (!rename(tmpfile, filename))
Junio C Hamano3be1f182009-03-27 23:14:39 -07001829 goto out;
Johannes Schindelin9e48b382005-10-26 01:41:20 +02001830 ret = errno;
Linus Torvalds230f1322005-10-08 15:54:01 -07001831 }
Alex Riesen691f1a22009-04-29 23:22:56 +02001832 unlink_or_warn(tmpfile);
Linus Torvalds230f1322005-10-08 15:54:01 -07001833 if (ret) {
1834 if (ret != EEXIST) {
Jeff King2c319882019-01-07 03:39:33 -05001835 return error_errno(_("unable to write file %s"), filename);
Linus Torvalds230f1322005-10-08 15:54:01 -07001836 }
1837 /* FIXME!!! Collision check here ? */
1838 }
1839
Junio C Hamano3be1f182009-03-27 23:14:39 -07001840out:
Matthieu Moy5256b002010-02-22 23:32:16 +01001841 if (adjust_shared_perm(filename))
Nguyễn Thái Ngọc Duy259328b2018-07-21 09:49:39 +02001842 return error(_("unable to set permission to '%s'"), filename);
Linus Torvalds230f1322005-10-08 15:54:01 -07001843 return 0;
1844}
1845
Ævar Arnfjörð Bjarmason44439c12022-02-05 00:48:32 +01001846static void hash_object_file_literally(const struct git_hash_algo *algo,
1847 const void *buf, unsigned long len,
1848 const char *type, struct object_id *oid)
Rene Scharfeabdc3fc2006-10-14 12:45:36 +02001849{
brian m. carlson1af64f72018-03-12 02:27:55 +00001850 char hdr[MAX_HEADER_LEN];
Jeff Kingef1286d2015-09-24 17:06:42 -04001851 int hdrlen = sizeof(hdr);
Ævar Arnfjörð Bjarmason44439c12022-02-05 00:48:32 +01001852
Ævar Arnfjörð Bjarmason2bbb28a2022-02-05 00:48:33 +01001853 write_object_file_prepare_literally(algo, buf, len, type, oid, hdr, &hdrlen);
Rene Scharfeabdc3fc2006-10-14 12:45:36 +02001854}
1855
Ævar Arnfjörð Bjarmason44439c12022-02-05 00:48:32 +01001856void hash_object_file(const struct git_hash_algo *algo, const void *buf,
1857 unsigned long len, enum object_type type,
1858 struct object_id *oid)
1859{
1860 hash_object_file_literally(algo, buf, len, type_name(type), oid);
Linus Torvalds93821bd2006-07-11 12:48:08 -07001861}
1862
Linus Torvaldse9039dd2008-06-10 18:47:18 -07001863/* Finalize a file on disk, and close it. */
Neeraj Singhc4e707f2022-03-30 18:14:15 +00001864static void close_loose_object(int fd, const char *filename)
Linus Torvaldse9039dd2008-06-10 18:47:18 -07001865{
Neeraj Singh020406e2022-03-10 22:43:21 +00001866 if (the_repository->objects->odb->will_destroy)
1867 goto out;
Neeraj Singhb3cecf42021-12-06 22:05:04 +00001868
Neeraj Singhc0f47522022-04-04 22:20:09 -07001869 if (batch_fsync_enabled(FSYNC_COMPONENT_LOOSE_OBJECT))
Junio C Hamano83937e92022-06-03 14:30:34 -07001870 fsync_loose_object_bulk_checkin(fd, filename);
Neeraj Singhc0f47522022-04-04 22:20:09 -07001871 else if (fsync_object_files > 0)
Neeraj Singhc4e707f2022-03-30 18:14:15 +00001872 fsync_or_die(fd, filename);
Neeraj Singh020406e2022-03-10 22:43:21 +00001873 else
1874 fsync_component_or_die(FSYNC_COMPONENT_LOOSE_OBJECT, fd,
Neeraj Singhc4e707f2022-03-30 18:14:15 +00001875 filename);
Neeraj Singh020406e2022-03-10 22:43:21 +00001876
1877out:
Linus Torvaldse9039dd2008-06-10 18:47:18 -07001878 if (close(fd) != 0)
Jeff King76011352019-01-07 03:39:24 -05001879 die_errno(_("error when closing loose object file"));
Linus Torvaldse9039dd2008-06-10 18:47:18 -07001880}
1881
Linus Torvalds5723fe72008-06-14 10:50:12 -07001882/* Size of directory component, including the ending '/' */
1883static inline int directory_size(const char *filename)
1884{
1885 const char *s = strrchr(filename, '/');
1886 if (!s)
1887 return 0;
1888 return s - filename + 1;
1889}
1890
1891/*
1892 * This creates a temporary file in the same directory as the final
1893 * 'filename'
1894 *
1895 * We want to avoid cross-directory filename renames, because those
1896 * can have problems on various filesystems (FAT, NFS, Coda).
1897 */
Jeff Kingd4b3d112015-09-24 17:07:49 -04001898static int create_tmpfile(struct strbuf *tmp, const char *filename)
Linus Torvalds5723fe72008-06-14 10:50:12 -07001899{
1900 int fd, dirlen = directory_size(filename);
1901
Jeff Kingd4b3d112015-09-24 17:07:49 -04001902 strbuf_reset(tmp);
1903 strbuf_add(tmp, filename, dirlen);
1904 strbuf_addstr(tmp, "tmp_obj_XXXXXX");
1905 fd = git_mkstemp_mode(tmp->buf, 0444);
Joey Hesscbacbf42008-11-20 13:56:28 -05001906 if (fd < 0 && dirlen && errno == ENOENT) {
Jeff Kingd4b3d112015-09-24 17:07:49 -04001907 /*
1908 * Make sure the directory exists; note that the contents
1909 * of the buffer are undefined after mkstemp returns an
1910 * error, so we have to rewrite the whole buffer from
1911 * scratch.
1912 */
1913 strbuf_reset(tmp);
1914 strbuf_add(tmp, filename, dirlen - 1);
1915 if (mkdir(tmp->buf, 0777) && errno != EEXIST)
Johan Herlandb2476a62013-10-27 12:35:43 +01001916 return -1;
Jeff Kingd4b3d112015-09-24 17:07:49 -04001917 if (adjust_shared_perm(tmp->buf))
Linus Torvalds5723fe72008-06-14 10:50:12 -07001918 return -1;
1919
1920 /* Try again */
Jeff Kingd4b3d112015-09-24 17:07:49 -04001921 strbuf_addstr(tmp, "/tmp_obj_XXXXXX");
1922 fd = git_mkstemp_mode(tmp->buf, 0444);
Linus Torvalds5723fe72008-06-14 10:50:12 -07001923 }
1924 return fd;
1925}
1926
Han Xin97a9db62022-06-11 10:44:17 +08001927/**
1928 * Common steps for loose object writers to start writing loose
1929 * objects:
1930 *
1931 * - Create tmpfile for the loose object.
1932 * - Setup zlib stream for compression.
1933 * - Start to feed header to zlib stream.
1934 *
1935 * Returns a "fd", which should later be provided to
1936 * end_loose_object_common().
1937 */
1938static int start_loose_object_common(struct strbuf *tmp_file,
1939 const char *filename, unsigned flags,
1940 git_zstream *stream,
1941 unsigned char *buf, size_t buflen,
1942 git_hash_ctx *c,
1943 char *hdr, int hdrlen)
1944{
1945 int fd;
1946
1947 fd = create_tmpfile(tmp_file, filename);
1948 if (fd < 0) {
1949 if (flags & HASH_SILENT)
1950 return -1;
1951 else if (errno == EACCES)
1952 return error(_("insufficient permission for adding "
1953 "an object to repository database %s"),
1954 get_object_directory());
1955 else
1956 return error_errno(
1957 _("unable to create temporary file"));
1958 }
1959
1960 /* Setup zlib stream for compression */
1961 git_deflate_init(stream, zlib_compression_level);
1962 stream->next_out = buf;
1963 stream->avail_out = buflen;
1964 the_hash_algo->init_fn(c);
1965
1966 /* Start to feed header to zlib stream */
1967 stream->next_in = (unsigned char *)hdr;
1968 stream->avail_in = hdrlen;
1969 while (git_deflate(stream, 0) == Z_OK)
1970 ; /* nothing */
1971 the_hash_algo->update_fn(c, hdr, hdrlen);
1972
1973 return fd;
1974}
1975
1976/**
Ævar Arnfjörð Bjarmason21e7d882022-06-11 10:44:18 +08001977 * Common steps for the inner git_deflate() loop for writing loose
1978 * objects. Returns what git_deflate() returns.
1979 */
1980static int write_loose_object_common(git_hash_ctx *c,
1981 git_zstream *stream, const int flush,
1982 unsigned char *in0, const int fd,
1983 unsigned char *compressed,
1984 const size_t compressed_len)
1985{
1986 int ret;
1987
1988 ret = git_deflate(stream, flush ? Z_FINISH : 0);
1989 the_hash_algo->update_fn(c, in0, stream->next_in - in0);
René Scharfed422d062022-12-13 20:35:07 +01001990 if (write_in_full(fd, compressed, stream->next_out - compressed) < 0)
1991 die_errno(_("unable to write loose object file"));
Ævar Arnfjörð Bjarmason21e7d882022-06-11 10:44:18 +08001992 stream->next_out = compressed;
1993 stream->avail_out = compressed_len;
1994
1995 return ret;
1996}
1997
1998/**
Han Xin97a9db62022-06-11 10:44:17 +08001999 * Common steps for loose object writers to end writing loose objects:
2000 *
2001 * - End the compression of zlib stream.
2002 * - Get the calculated oid to "oid".
2003 */
2004static int end_loose_object_common(git_hash_ctx *c, git_zstream *stream,
2005 struct object_id *oid)
2006{
2007 int ret;
2008
2009 ret = git_deflate_end_gently(stream);
2010 if (ret != Z_OK)
2011 return ret;
2012 the_hash_algo->final_oid_fn(oid, c);
2013
2014 return Z_OK;
2015}
2016
Patryk Obara3fc72812018-01-28 01:13:21 +01002017static int write_loose_object(const struct object_id *oid, char *hdr,
2018 int hdrlen, const void *buf, unsigned long len,
Ævar Arnfjörð Bjarmason4ef91a22021-10-12 16:30:49 +02002019 time_t mtime, unsigned flags)
Linus Torvalds0fcfd162005-04-18 13:04:43 -07002020{
Jeff King915308b2009-01-29 00:56:34 -05002021 int fd, ret;
Nicolas Pitre9892beb2010-02-20 23:27:31 -05002022 unsigned char compressed[4096];
Junio C Hamanoef49a7a2011-06-10 11:52:15 -07002023 git_zstream stream;
brian m. carlson18e25882018-02-01 02:18:41 +00002024 git_hash_ctx c;
Patryk Obara3fc72812018-01-28 01:13:21 +01002025 struct object_id parano_oid;
Jeff Kingd4b3d112015-09-24 17:07:49 -04002026 static struct strbuf tmp_file = STRBUF_INIT;
Christian Couderea657732018-01-17 18:54:54 +01002027 static struct strbuf filename = STRBUF_INIT;
Linus Torvaldsa44c9a52005-04-25 10:19:53 -07002028
Neeraj Singhc0f47522022-04-04 22:20:09 -07002029 if (batch_fsync_enabled(FSYNC_COMPONENT_LOOSE_OBJECT))
2030 prepare_loose_object_bulk_checkin();
2031
Jeff King514c5fd2019-01-07 03:35:42 -05002032 loose_object_path(the_repository, &filename, oid);
Christian Couderea657732018-01-17 18:54:54 +01002033
Han Xin97a9db62022-06-11 10:44:17 +08002034 fd = start_loose_object_common(&tmp_file, filename.buf, flags,
2035 &stream, compressed, sizeof(compressed),
2036 &c, hdr, hdrlen);
2037 if (fd < 0)
2038 return -1;
Linus Torvaldsa44c9a52005-04-25 10:19:53 -07002039
2040 /* Then the data itself.. */
Jeff Kingc00e6572010-04-01 20:03:18 -04002041 stream.next_in = (void *)buf;
Linus Torvaldsa44c9a52005-04-25 10:19:53 -07002042 stream.avail_in = len;
Nicolas Pitre9892beb2010-02-20 23:27:31 -05002043 do {
Nicolas Pitre748af442010-02-21 15:48:06 -05002044 unsigned char *in0 = stream.next_in;
Ævar Arnfjörð Bjarmason21e7d882022-06-11 10:44:18 +08002045
2046 ret = write_loose_object_common(&c, &stream, 1, in0, fd,
2047 compressed, sizeof(compressed));
Nicolas Pitre9892beb2010-02-20 23:27:31 -05002048 } while (ret == Z_OK);
2049
Linus Torvaldsac54c272007-03-20 11:38:34 -07002050 if (ret != Z_STREAM_END)
Nguyễn Thái Ngọc Duy259328b2018-07-21 09:49:39 +02002051 die(_("unable to deflate new object %s (%d)"), oid_to_hex(oid),
Patryk Obara3fc72812018-01-28 01:13:21 +01002052 ret);
Han Xin97a9db62022-06-11 10:44:17 +08002053 ret = end_loose_object_common(&c, &stream, &parano_oid);
Linus Torvaldsac54c272007-03-20 11:38:34 -07002054 if (ret != Z_OK)
Nguyễn Thái Ngọc Duy259328b2018-07-21 09:49:39 +02002055 die(_("deflateEnd on object %s failed (%d)"), oid_to_hex(oid),
Patryk Obara3fc72812018-01-28 01:13:21 +01002056 ret);
Jeff King9001dc22018-08-28 17:22:48 -04002057 if (!oideq(oid, &parano_oid))
Nguyễn Thái Ngọc Duy259328b2018-07-21 09:49:39 +02002058 die(_("confused by unstable object source data for %s"),
Patryk Obara3fc72812018-01-28 01:13:21 +01002059 oid_to_hex(oid));
Linus Torvaldsac54c272007-03-20 11:38:34 -07002060
Neeraj Singhc4e707f2022-03-30 18:14:15 +00002061 close_loose_object(fd, tmp_file.buf);
Linus Torvalds0fcfd162005-04-18 13:04:43 -07002062
Nicolas Pitrebbac7312008-05-14 01:32:48 -04002063 if (mtime) {
2064 struct utimbuf utb;
2065 utb.actime = mtime;
2066 utb.modtime = mtime;
Ævar Arnfjörð Bjarmason4ef91a22021-10-12 16:30:49 +02002067 if (utime(tmp_file.buf, &utb) < 0 &&
2068 !(flags & HASH_SILENT))
Nguyễn Thái Ngọc Duy259328b2018-07-21 09:49:39 +02002069 warning_errno(_("failed utime() on %s"), tmp_file.buf);
Nicolas Pitrebbac7312008-05-14 01:32:48 -04002070 }
2071
Christian Couderea657732018-01-17 18:54:54 +01002072 return finalize_object_file(tmp_file.buf, filename.buf);
Linus Torvalds0fcfd162005-04-18 13:04:43 -07002073}
Daniel Barkalow8237b182005-04-23 18:47:23 -07002074
brian m. carlson6862ebb2018-05-02 00:25:34 +00002075static int freshen_loose_object(const struct object_id *oid)
Jeff King33d42212014-10-15 18:42:22 -04002076{
brian m. carlson6862ebb2018-05-02 00:25:34 +00002077 return check_and_freshen(oid, 1);
Jeff King33d42212014-10-15 18:42:22 -04002078}
2079
brian m. carlson6862ebb2018-05-02 00:25:34 +00002080static int freshen_packed_object(const struct object_id *oid)
Jeff King33d42212014-10-15 18:42:22 -04002081{
2082 struct pack_entry e;
brian m. carlson544443c2018-05-02 00:25:35 +00002083 if (!find_pack_entry(the_repository, oid, &e))
Jeff Kingee1c6c32015-04-20 15:55:00 -04002084 return 0;
Taylor Blaua6131642022-05-20 19:18:17 -04002085 if (e.p->is_cruft)
2086 return 0;
Jeff Kingee1c6c32015-04-20 15:55:00 -04002087 if (e.p->freshened)
2088 return 1;
2089 if (!freshen_file(e.p->pack_name))
2090 return 0;
2091 e.p->freshened = 1;
2092 return 1;
Jeff King33d42212014-10-15 18:42:22 -04002093}
2094
Han Xin2b6070a2022-06-11 10:44:19 +08002095int stream_loose_object(struct input_stream *in_stream, size_t len,
2096 struct object_id *oid)
2097{
2098 int fd, ret, err = 0, flush = 0;
2099 unsigned char compressed[4096];
2100 git_zstream stream;
2101 git_hash_ctx c;
2102 struct strbuf tmp_file = STRBUF_INIT;
2103 struct strbuf filename = STRBUF_INIT;
2104 int dirlen;
2105 char hdr[MAX_HEADER_LEN];
2106 int hdrlen;
2107
2108 if (batch_fsync_enabled(FSYNC_COMPONENT_LOOSE_OBJECT))
2109 prepare_loose_object_bulk_checkin();
2110
2111 /* Since oid is not determined, save tmp file to odb path. */
2112 strbuf_addf(&filename, "%s/", get_object_directory());
2113 hdrlen = format_object_header(hdr, sizeof(hdr), OBJ_BLOB, len);
2114
2115 /*
2116 * Common steps for write_loose_object and stream_loose_object to
2117 * start writing loose objects:
2118 *
2119 * - Create tmpfile for the loose object.
2120 * - Setup zlib stream for compression.
2121 * - Start to feed header to zlib stream.
2122 */
2123 fd = start_loose_object_common(&tmp_file, filename.buf, 0,
2124 &stream, compressed, sizeof(compressed),
2125 &c, hdr, hdrlen);
2126 if (fd < 0) {
2127 err = -1;
2128 goto cleanup;
2129 }
2130
2131 /* Then the data itself.. */
2132 do {
2133 unsigned char *in0 = stream.next_in;
2134
2135 if (!stream.avail_in && !in_stream->is_finished) {
2136 const void *in = in_stream->read(in_stream, &stream.avail_in);
2137 stream.next_in = (void *)in;
2138 in0 = (unsigned char *)in;
2139 /* All data has been read. */
2140 if (in_stream->is_finished)
2141 flush = 1;
2142 }
2143 ret = write_loose_object_common(&c, &stream, flush, in0, fd,
2144 compressed, sizeof(compressed));
2145 /*
2146 * Unlike write_loose_object(), we do not have the entire
2147 * buffer. If we get Z_BUF_ERROR due to too few input bytes,
2148 * then we'll replenish them in the next input_stream->read()
2149 * call when we loop.
2150 */
2151 } while (ret == Z_OK || ret == Z_BUF_ERROR);
2152
2153 if (stream.total_in != len + hdrlen)
2154 die(_("write stream object %ld != %"PRIuMAX), stream.total_in,
2155 (uintmax_t)len + hdrlen);
2156
2157 /*
2158 * Common steps for write_loose_object and stream_loose_object to
2159 * end writing loose oject:
2160 *
2161 * - End the compression of zlib stream.
2162 * - Get the calculated oid.
2163 */
2164 if (ret != Z_STREAM_END)
2165 die(_("unable to stream deflate new object (%d)"), ret);
2166 ret = end_loose_object_common(&c, &stream, oid);
2167 if (ret != Z_OK)
2168 die(_("deflateEnd on stream object failed (%d)"), ret);
2169 close_loose_object(fd, tmp_file.buf);
2170
2171 if (freshen_packed_object(oid) || freshen_loose_object(oid)) {
2172 unlink_or_warn(tmp_file.buf);
2173 goto cleanup;
2174 }
2175
2176 loose_object_path(the_repository, &filename, oid);
2177
2178 /* We finally know the object path, and create the missing dir. */
2179 dirlen = directory_size(filename.buf);
2180 if (dirlen) {
2181 struct strbuf dir = STRBUF_INIT;
2182 strbuf_add(&dir, filename.buf, dirlen);
2183
2184 if (mkdir_in_gitdir(dir.buf) && errno != EEXIST) {
2185 err = error_errno(_("unable to create directory %s"), dir.buf);
2186 strbuf_release(&dir);
2187 goto cleanup;
2188 }
2189 strbuf_release(&dir);
2190 }
2191
2192 err = finalize_object_file(tmp_file.buf, filename.buf);
2193cleanup:
2194 strbuf_release(&tmp_file);
2195 strbuf_release(&filename);
2196 return err;
2197}
2198
Ævar Arnfjörð Bjarmason4ef91a22021-10-12 16:30:49 +02002199int write_object_file_flags(const void *buf, unsigned long len,
Ævar Arnfjörð Bjarmasonc80d2262022-02-05 00:48:26 +01002200 enum object_type type, struct object_id *oid,
Ævar Arnfjörð Bjarmason4ef91a22021-10-12 16:30:49 +02002201 unsigned flags)
Nicolas Pitrebbac7312008-05-14 01:32:48 -04002202{
brian m. carlson1af64f72018-03-12 02:27:55 +00002203 char hdr[MAX_HEADER_LEN];
Jeff Kingef1286d2015-09-24 17:06:42 -04002204 int hdrlen = sizeof(hdr);
Nicolas Pitrebbac7312008-05-14 01:32:48 -04002205
2206 /* Normally if we have it in the pack then we do not bother writing
2207 * it out into .git/objects/??/?{38} file.
2208 */
Matheus Tavares7ad5c442020-01-30 17:32:21 -03002209 write_object_file_prepare(the_hash_algo, buf, len, type, oid, hdr,
2210 &hdrlen);
brian m. carlson6862ebb2018-05-02 00:25:34 +00002211 if (freshen_packed_object(oid) || freshen_loose_object(oid))
Nicolas Pitrebbac7312008-05-14 01:32:48 -04002212 return 0;
Ævar Arnfjörð Bjarmason4ef91a22021-10-12 16:30:49 +02002213 return write_loose_object(oid, hdr, hdrlen, buf, len, 0, flags);
Nicolas Pitrebbac7312008-05-14 01:32:48 -04002214}
2215
Ævar Arnfjörð Bjarmason0ff7b4f2022-02-05 00:48:31 +01002216int write_object_file_literally(const void *buf, unsigned long len,
2217 const char *type, struct object_id *oid,
2218 unsigned flags)
Eric Sunshine0c3db672015-05-04 03:25:15 -04002219{
2220 char *header;
2221 int hdrlen, status = 0;
2222
2223 /* type string, SP, %lu of the length plus NUL must fit this */
brian m. carlson1af64f72018-03-12 02:27:55 +00002224 hdrlen = strlen(type) + MAX_HEADER_LEN;
Jeff Kingef1286d2015-09-24 17:06:42 -04002225 header = xmalloc(hdrlen);
Ævar Arnfjörð Bjarmason2bbb28a2022-02-05 00:48:33 +01002226 write_object_file_prepare_literally(the_hash_algo, buf, len, type,
2227 oid, header, &hdrlen);
Eric Sunshine0c3db672015-05-04 03:25:15 -04002228
2229 if (!(flags & HASH_WRITE_OBJECT))
2230 goto cleanup;
brian m. carlson6862ebb2018-05-02 00:25:34 +00002231 if (freshen_packed_object(oid) || freshen_loose_object(oid))
Eric Sunshine0c3db672015-05-04 03:25:15 -04002232 goto cleanup;
Ævar Arnfjörð Bjarmason4ef91a22021-10-12 16:30:49 +02002233 status = write_loose_object(oid, header, hdrlen, buf, len, 0, 0);
Eric Sunshine0c3db672015-05-04 03:25:15 -04002234
2235cleanup:
2236 free(header);
2237 return status;
2238}
2239
Patryk Obara4bdb70a2018-01-28 01:13:20 +01002240int force_object_loose(const struct object_id *oid, time_t mtime)
Nicolas Pitrebbac7312008-05-14 01:32:48 -04002241{
Nicolas Pitrebbac7312008-05-14 01:32:48 -04002242 void *buf;
2243 unsigned long len;
Jeff Kingb25562e2023-01-07 08:48:55 -05002244 struct object_info oi = OBJECT_INFO_INIT;
Nicolas Pitrebbac7312008-05-14 01:32:48 -04002245 enum object_type type;
brian m. carlson1af64f72018-03-12 02:27:55 +00002246 char hdr[MAX_HEADER_LEN];
Nicolas Pitrebbac7312008-05-14 01:32:48 -04002247 int hdrlen;
Björn Steinbrink1fb23e62008-10-18 02:37:31 +02002248 int ret;
Nicolas Pitrebbac7312008-05-14 01:32:48 -04002249
brian m. carlson6862ebb2018-05-02 00:25:34 +00002250 if (has_loose_object(oid))
Nicolas Pitrebbac7312008-05-14 01:32:48 -04002251 return 0;
Jeff Kingb25562e2023-01-07 08:48:55 -05002252 oi.typep = &type;
2253 oi.sizep = &len;
2254 oi.contentp = &buf;
2255 if (oid_object_info_extended(the_repository, oid, &oi, 0))
Jeff King2c319882019-01-07 03:39:33 -05002256 return error(_("cannot read object for %s"), oid_to_hex(oid));
Ævar Arnfjörð Bjarmasonb04cdea2022-02-05 00:48:25 +01002257 hdrlen = format_object_header(hdr, sizeof(hdr), type, len);
Ævar Arnfjörð Bjarmason4ef91a22021-10-12 16:30:49 +02002258 ret = write_loose_object(oid, hdr, hdrlen, buf, len, mtime, 0);
Björn Steinbrink1fb23e62008-10-18 02:37:31 +02002259 free(buf);
2260
2261 return ret;
Nicolas Pitrebbac7312008-05-14 01:32:48 -04002262}
2263
Jonathan Tan1d8d9cb2020-08-05 16:06:49 -07002264int has_object(struct repository *r, const struct object_id *oid,
2265 unsigned flags)
2266{
2267 int quick = !(flags & HAS_OBJECT_RECHECK_PACKED);
2268 unsigned object_info_flags = OBJECT_INFO_SKIP_FETCH_OBJECT |
2269 (quick ? OBJECT_INFO_QUICK : 0);
2270
2271 if (!startup_info->have_repository)
2272 return 0;
2273 return oid_object_info_extended(r, oid, NULL, object_info_flags) >= 0;
2274}
2275
Junio C Hamanocba595a2019-02-06 22:05:27 -08002276int repo_has_object_file_with_flags(struct repository *r,
2277 const struct object_id *oid, int flags)
Daniel Barkalow8237b182005-04-23 18:47:23 -07002278{
Jonathan Nieder3e8b7d32017-04-11 15:47:13 -07002279 if (!startup_info->have_repository)
2280 return 0;
Jonathan Tan9c8a2942020-01-02 12:16:30 -08002281 return oid_object_info_extended(r, oid, NULL, flags) >= 0;
Daniel Barkalow8237b182005-04-23 18:47:23 -07002282}
Junio C Hamano74400e72005-05-01 23:45:49 -07002283
Stefan Beller9b45f492018-11-13 16:12:48 -08002284int repo_has_object_file(struct repository *r,
2285 const struct object_id *oid)
brian m. carlsonb419aa22015-11-10 02:22:19 +00002286{
Junio C Hamanocba595a2019-02-06 22:05:27 -08002287 return repo_has_object_file_with_flags(r, oid, 0);
Jeff King5827a032016-10-13 12:53:44 -04002288}
2289
Jeff King69bbbe42023-01-18 15:44:12 -05002290/*
2291 * We can't use the normal fsck_error_function() for index_mem(),
2292 * because we don't yet have a valid oid for it to report. Instead,
2293 * report the minimal fsck error here, and rely on the caller to
2294 * give more context.
2295 */
2296static int hash_format_check_report(struct fsck_options *opts,
2297 const struct object_id *oid,
2298 enum object_type object_type,
2299 enum fsck_msg_type msg_type,
2300 enum fsck_msg_id msg_id,
2301 const char *message)
Nguyễn Thái Ngọc Duyc879daa2011-02-05 17:52:21 +07002302{
Jeff King69bbbe42023-01-18 15:44:12 -05002303 error(_("object fails fsck: %s"), message);
2304 return 1;
Nguyễn Thái Ngọc Duyc879daa2011-02-05 17:52:21 +07002305}
2306
Nguyễn Thái Ngọc Duy58bf2a42018-09-21 17:57:31 +02002307static int index_mem(struct index_state *istate,
2308 struct object_id *oid, void *buf, size_t size,
Junio C Hamanoc4ce46f2011-05-08 01:47:33 -07002309 enum object_type type,
2310 const char *path, unsigned flags)
Björn Engelmanne7332f92006-05-23 20:19:04 +02002311{
Ævar Arnfjörð Bjarmason63e05f92022-02-05 00:48:24 +01002312 int ret = 0;
Ævar Arnfjörð Bjarmasonbbea0dd2022-02-05 00:48:23 +01002313 int re_allocated = 0;
Junio C Hamanoc4ce46f2011-05-08 01:47:33 -07002314 int write_object = flags & HASH_WRITE_OBJECT;
Junio C Hamano74400e72005-05-01 23:45:49 -07002315
Bryan Larsen7672db22005-07-08 16:51:55 -07002316 if (!type)
Junio C Hamanoedaec3f2007-02-28 11:45:56 -08002317 type = OBJ_BLOB;
Linus Torvalds6c510be2007-02-13 11:07:23 -08002318
2319 /*
2320 * Convert blobs to git internal format
2321 */
Dmitry Potapov43df4f82008-08-03 08:39:16 +04002322 if ((type == OBJ_BLOB) && path) {
Brandon Caseyf285a2d2008-10-09 14:12:12 -05002323 struct strbuf nbuf = STRBUF_INIT;
Nguyễn Thái Ngọc Duy58bf2a42018-09-21 17:57:31 +02002324 if (convert_to_git(istate, path, buf, size, &nbuf,
Torsten Bögershausen8462ff42018-01-13 23:49:31 +01002325 get_conv_flags(flags))) {
Pierre Habouzitb315c5c2007-09-27 12:58:23 +02002326 buf = strbuf_detach(&nbuf, &size);
Linus Torvalds6c510be2007-02-13 11:07:23 -08002327 re_allocated = 1;
2328 }
2329 }
Junio C Hamanoc4ce46f2011-05-08 01:47:33 -07002330 if (flags & HASH_FORMAT_CHECK) {
Jeff King69bbbe42023-01-18 15:44:12 -05002331 struct fsck_options opts = FSCK_OPTIONS_DEFAULT;
2332
2333 opts.strict = 1;
2334 opts.error_func = hash_format_check_report;
2335 if (fsck_buffer(null_oid(), type, buf, size, &opts))
2336 die(_("refusing to create malformed object"));
2337 fsck_finish(&opts);
Nguyễn Thái Ngọc Duyc879daa2011-02-05 17:52:21 +07002338 }
Linus Torvalds6c510be2007-02-13 11:07:23 -08002339
Bryan Larsen7672db22005-07-08 16:51:55 -07002340 if (write_object)
Ævar Arnfjörð Bjarmasonc80d2262022-02-05 00:48:26 +01002341 ret = write_object_file(buf, size, type, oid);
Rene Scharfeabdc3fc2006-10-14 12:45:36 +02002342 else
Ævar Arnfjörð Bjarmason44439c12022-02-05 00:48:32 +01002343 hash_object_file(the_hash_algo, buf, size, type, oid);
Dmitry Potapov43df4f82008-08-03 08:39:16 +04002344 if (re_allocated)
Linus Torvalds6c510be2007-02-13 11:07:23 -08002345 free(buf);
Dmitry Potapov43df4f82008-08-03 08:39:16 +04002346 return ret;
2347}
2348
Nguyễn Thái Ngọc Duy58bf2a42018-09-21 17:57:31 +02002349static int index_stream_convert_blob(struct index_state *istate,
2350 struct object_id *oid,
2351 int fd,
2352 const char *path,
2353 unsigned flags)
Steffen Prohaska9035d752014-08-26 17:23:25 +02002354{
Ævar Arnfjörð Bjarmason63e05f92022-02-05 00:48:24 +01002355 int ret = 0;
Steffen Prohaska9035d752014-08-26 17:23:25 +02002356 const int write_object = flags & HASH_WRITE_OBJECT;
2357 struct strbuf sbuf = STRBUF_INIT;
2358
2359 assert(path);
Nguyễn Thái Ngọc Duy58bf2a42018-09-21 17:57:31 +02002360 assert(would_convert_to_git_filter_fd(istate, path));
Steffen Prohaska9035d752014-08-26 17:23:25 +02002361
Nguyễn Thái Ngọc Duy58bf2a42018-09-21 17:57:31 +02002362 convert_to_git_filter_fd(istate, path, fd, &sbuf,
Torsten Bögershausen8462ff42018-01-13 23:49:31 +01002363 get_conv_flags(flags));
Steffen Prohaska9035d752014-08-26 17:23:25 +02002364
2365 if (write_object)
Ævar Arnfjörð Bjarmasonc80d2262022-02-05 00:48:26 +01002366 ret = write_object_file(sbuf.buf, sbuf.len, OBJ_BLOB,
Patryk Obaraa09c9852018-01-28 01:13:19 +01002367 oid);
Steffen Prohaska9035d752014-08-26 17:23:25 +02002368 else
Ævar Arnfjörð Bjarmason44439c12022-02-05 00:48:32 +01002369 hash_object_file(the_hash_algo, sbuf.buf, sbuf.len, OBJ_BLOB,
2370 oid);
Steffen Prohaska9035d752014-08-26 17:23:25 +02002371 strbuf_release(&sbuf);
2372 return ret;
2373}
2374
Nguyễn Thái Ngọc Duy58bf2a42018-09-21 17:57:31 +02002375static int index_pipe(struct index_state *istate, struct object_id *oid,
2376 int fd, enum object_type type,
Junio C Hamano7b41e1e2011-05-08 01:47:34 -07002377 const char *path, unsigned flags)
2378{
2379 struct strbuf sbuf = STRBUF_INIT;
2380 int ret;
2381
2382 if (strbuf_read(&sbuf, fd, 4096) >= 0)
Nguyễn Thái Ngọc Duy58bf2a42018-09-21 17:57:31 +02002383 ret = index_mem(istate, oid, sbuf.buf, sbuf.len, type, path, flags);
Junio C Hamano7b41e1e2011-05-08 01:47:34 -07002384 else
2385 ret = -1;
2386 strbuf_release(&sbuf);
2387 return ret;
2388}
2389
Dmitry Potapovea68b0c2010-02-21 09:32:19 +03002390#define SMALL_FILE_SIZE (32*1024)
2391
Nguyễn Thái Ngọc Duy58bf2a42018-09-21 17:57:31 +02002392static int index_core(struct index_state *istate,
2393 struct object_id *oid, int fd, size_t size,
Junio C Hamano7b41e1e2011-05-08 01:47:34 -07002394 enum object_type type, const char *path,
2395 unsigned flags)
Dmitry Potapov43df4f82008-08-03 08:39:16 +04002396{
2397 int ret;
Dmitry Potapov43df4f82008-08-03 08:39:16 +04002398
Junio C Hamano7b41e1e2011-05-08 01:47:34 -07002399 if (!size) {
Nguyễn Thái Ngọc Duy58bf2a42018-09-21 17:57:31 +02002400 ret = index_mem(istate, oid, "", size, type, path, flags);
Dmitry Potapovea68b0c2010-02-21 09:32:19 +03002401 } else if (size <= SMALL_FILE_SIZE) {
2402 char *buf = xmalloc(size);
Jeff King90dca672017-09-27 02:01:07 -04002403 ssize_t read_result = read_in_full(fd, buf, size);
2404 if (read_result < 0)
Nguyễn Thái Ngọc Duy259328b2018-07-21 09:49:39 +02002405 ret = error_errno(_("read error while indexing %s"),
Jeff King90dca672017-09-27 02:01:07 -04002406 path ? path : "<unknown>");
2407 else if (read_result != size)
Nguyễn Thái Ngọc Duy259328b2018-07-21 09:49:39 +02002408 ret = error(_("short read while indexing %s"),
Jeff King90dca672017-09-27 02:01:07 -04002409 path ? path : "<unknown>");
Dmitry Potapovea68b0c2010-02-21 09:32:19 +03002410 else
Nguyễn Thái Ngọc Duy58bf2a42018-09-21 17:57:31 +02002411 ret = index_mem(istate, oid, buf, size, type, path, flags);
Dmitry Potapovea68b0c2010-02-21 09:32:19 +03002412 free(buf);
Dmitry Potapov08bda202010-05-11 01:38:17 +04002413 } else {
Dmitry Potapov43df4f82008-08-03 08:39:16 +04002414 void *buf = xmmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
Nguyễn Thái Ngọc Duy58bf2a42018-09-21 17:57:31 +02002415 ret = index_mem(istate, oid, buf, size, type, path, flags);
Linus Torvaldsaac17942005-05-03 11:46:16 -07002416 munmap(buf, size);
Dmitry Potapov08bda202010-05-11 01:38:17 +04002417 }
Junio C Hamano7b41e1e2011-05-08 01:47:34 -07002418 return ret;
2419}
2420
Junio C Hamano4dd1fbc2011-05-08 01:47:35 -07002421/*
Junio C Hamano568508e2011-10-28 14:48:40 -07002422 * This creates one packfile per large blob unless bulk-checkin
2423 * machinery is "plugged".
Junio C Hamano4dd1fbc2011-05-08 01:47:35 -07002424 *
2425 * This also bypasses the usual "convert-to-git" dance, and that is on
2426 * purpose. We could write a streaming version of the converting
2427 * functions and insert that before feeding the data to fast-import
Jeff King4f22b102012-02-24 17:10:17 -05002428 * (or equivalent in-core API described above). However, that is
2429 * somewhat complicated, as we do not know the size of the filter
2430 * result, which we need to know beforehand when writing a git object.
2431 * Since the primary motivation for trying to stream from the working
2432 * tree file and to avoid mmaping it in core is to deal with large
2433 * binary blobs, they generally do not want to get any conversion, and
2434 * callers should avoid this code path when filters are requested.
Junio C Hamano4dd1fbc2011-05-08 01:47:35 -07002435 */
Patryk Obara7d5e1dc2017-08-20 22:09:31 +02002436static int index_stream(struct object_id *oid, int fd, size_t size,
Junio C Hamano4dd1fbc2011-05-08 01:47:35 -07002437 enum object_type type, const char *path,
2438 unsigned flags)
2439{
brian m. carlson68ee6df2018-03-12 02:27:21 +00002440 return index_bulk_checkin(oid, fd, size, type, path, flags);
Junio C Hamano4dd1fbc2011-05-08 01:47:35 -07002441}
2442
Nguyễn Thái Ngọc Duy58bf2a42018-09-21 17:57:31 +02002443int index_fd(struct index_state *istate, struct object_id *oid,
2444 int fd, struct stat *st,
Junio C Hamano7b41e1e2011-05-08 01:47:34 -07002445 enum object_type type, const char *path, unsigned flags)
2446{
2447 int ret;
Junio C Hamano7b41e1e2011-05-08 01:47:34 -07002448
Steffen Prohaska9079ab72014-09-21 12:03:26 +02002449 /*
2450 * Call xsize_t() only when needed to avoid potentially unnecessary
2451 * die() for large files.
2452 */
Nguyễn Thái Ngọc Duy58bf2a42018-09-21 17:57:31 +02002453 if (type == OBJ_BLOB && path && would_convert_to_git_filter_fd(istate, path))
2454 ret = index_stream_convert_blob(istate, oid, fd, path, flags);
Steffen Prohaska9035d752014-08-26 17:23:25 +02002455 else if (!S_ISREG(st->st_mode))
Nguyễn Thái Ngọc Duy58bf2a42018-09-21 17:57:31 +02002456 ret = index_pipe(istate, oid, fd, type, path, flags);
Steffen Prohaska9079ab72014-09-21 12:03:26 +02002457 else if (st->st_size <= big_file_threshold || type != OBJ_BLOB ||
Nguyễn Thái Ngọc Duy58bf2a42018-09-21 17:57:31 +02002458 (path && would_convert_to_git(istate, path)))
2459 ret = index_core(istate, oid, fd, xsize_t(st->st_size),
2460 type, path, flags);
Junio C Hamano4dd1fbc2011-05-08 01:47:35 -07002461 else
Patryk Obara7d5e1dc2017-08-20 22:09:31 +02002462 ret = index_stream(oid, fd, xsize_t(st->st_size), type, path,
Steffen Prohaska9079ab72014-09-21 12:03:26 +02002463 flags);
Dmitry Potapov43df4f82008-08-03 08:39:16 +04002464 close(fd);
Linus Torvaldsaac17942005-05-03 11:46:16 -07002465 return ret;
Junio C Hamano74400e72005-05-01 23:45:49 -07002466}
Junio C Hamanoec1fcc12005-10-07 03:42:00 -07002467
Nguyễn Thái Ngọc Duy58bf2a42018-09-21 17:57:31 +02002468int index_path(struct index_state *istate, struct object_id *oid,
2469 const char *path, struct stat *st, unsigned flags)
Junio C Hamanoec1fcc12005-10-07 03:42:00 -07002470{
2471 int fd;
Linus Torvaldsb760d3a2008-12-17 09:51:53 -08002472 struct strbuf sb = STRBUF_INIT;
Rene Scharfeea8e0292017-08-30 20:00:29 +02002473 int rc = 0;
Junio C Hamanoec1fcc12005-10-07 03:42:00 -07002474
2475 switch (st->st_mode & S_IFMT) {
2476 case S_IFREG:
2477 fd = open(path, O_RDONLY);
2478 if (fd < 0)
Nguyễn Thái Ngọc Duy7616c6c2016-05-08 16:47:56 +07002479 return error_errno("open(\"%s\")", path);
Nguyễn Thái Ngọc Duy58bf2a42018-09-21 17:57:31 +02002480 if (index_fd(istate, oid, fd, st, OBJ_BLOB, path, flags) < 0)
Nguyễn Thái Ngọc Duy259328b2018-07-21 09:49:39 +02002481 return error(_("%s: failed to insert into database"),
Junio C Hamanoec1fcc12005-10-07 03:42:00 -07002482 path);
2483 break;
2484 case S_IFLNK:
Nguyễn Thái Ngọc Duy7616c6c2016-05-08 16:47:56 +07002485 if (strbuf_readlink(&sb, path, st->st_size))
2486 return error_errno("readlink(\"%s\")", path);
Junio C Hamanoc4ce46f2011-05-08 01:47:33 -07002487 if (!(flags & HASH_WRITE_OBJECT))
Matheus Tavares2dcde202020-01-30 17:32:22 -03002488 hash_object_file(the_hash_algo, sb.buf, sb.len,
Ævar Arnfjörð Bjarmason44439c12022-02-05 00:48:32 +01002489 OBJ_BLOB, oid);
Ævar Arnfjörð Bjarmasonc80d2262022-02-05 00:48:26 +01002490 else if (write_object_file(sb.buf, sb.len, OBJ_BLOB, oid))
Nguyễn Thái Ngọc Duy259328b2018-07-21 09:49:39 +02002491 rc = error(_("%s: failed to insert into database"), path);
Linus Torvaldsb760d3a2008-12-17 09:51:53 -08002492 strbuf_release(&sb);
Junio C Hamanoec1fcc12005-10-07 03:42:00 -07002493 break;
Linus Torvaldsf35a6d32007-04-09 21:20:29 -07002494 case S_IFDIR:
brian m. carlsona98e6102017-10-15 22:07:07 +00002495 return resolve_gitlink_ref(path, "HEAD", oid);
Junio C Hamanoec1fcc12005-10-07 03:42:00 -07002496 default:
Nguyễn Thái Ngọc Duy259328b2018-07-21 09:49:39 +02002497 return error(_("%s: unsupported file type"), path);
Junio C Hamanoec1fcc12005-10-07 03:42:00 -07002498 }
Rene Scharfeea8e0292017-08-30 20:00:29 +02002499 return rc;
Junio C Hamanoec1fcc12005-10-07 03:42:00 -07002500}
Junio C Hamanoa69e5422007-01-22 21:55:18 -08002501
2502int read_pack_header(int fd, struct pack_header *header)
2503{
Jeff Kingf48ecd32017-09-13 14:47:22 -04002504 if (read_in_full(fd, header, sizeof(*header)) != sizeof(*header))
Heikki Orsilac697ad12008-05-03 16:27:26 +03002505 /* "eof before pack header was fully read" */
2506 return PH_ERROR_EOF;
2507
Junio C Hamanoa69e5422007-01-22 21:55:18 -08002508 if (header->hdr_signature != htonl(PACK_SIGNATURE))
2509 /* "protocol error (pack signature mismatch detected)" */
2510 return PH_ERROR_PACK_SIGNATURE;
2511 if (!pack_version_ok(header->hdr_version))
2512 /* "protocol error (pack version unsupported)" */
2513 return PH_ERROR_PROTOCOL;
2514 return 0;
2515}
Jeff King40d52ff2010-04-01 20:05:23 -04002516
brian m. carlsone816caa2018-03-12 02:27:42 +00002517void assert_oid_type(const struct object_id *oid, enum object_type expect)
Jeff King40d52ff2010-04-01 20:05:23 -04002518{
Stefan Beller0df8e962018-04-25 11:20:59 -07002519 enum object_type type = oid_object_info(the_repository, oid, NULL);
Jeff King40d52ff2010-04-01 20:05:23 -04002520 if (type < 0)
Nguyễn Thái Ngọc Duy259328b2018-07-21 09:49:39 +02002521 die(_("%s is not a valid object"), oid_to_hex(oid));
Jeff King40d52ff2010-04-01 20:05:23 -04002522 if (type != expect)
Nguyễn Thái Ngọc Duy259328b2018-07-21 09:49:39 +02002523 die(_("%s is not a valid '%s' object"), oid_to_hex(oid),
Brandon Williamsdebca9d2018-02-14 10:59:24 -08002524 type_name(expect));
Jeff King40d52ff2010-04-01 20:05:23 -04002525}
Jeff King27e1e222014-10-15 18:38:55 -04002526
René Scharfe70c49052017-06-24 16:09:39 +02002527int for_each_file_in_obj_subdir(unsigned int subdir_nr,
René Scharfecc817ca2017-06-22 20:19:48 +02002528 struct strbuf *path,
2529 each_loose_object_fn obj_cb,
2530 each_loose_cruft_fn cruft_cb,
2531 each_loose_subdir_fn subdir_cb,
2532 void *data)
Jeff King27e1e222014-10-15 18:38:55 -04002533{
René Scharfe0375f472017-06-24 14:12:30 +02002534 size_t origlen, baselen;
2535 DIR *dir;
Jeff King27e1e222014-10-15 18:38:55 -04002536 struct dirent *de;
2537 int r = 0;
René Scharfe62a24c82017-10-31 14:50:06 +01002538 struct object_id oid;
Jeff King27e1e222014-10-15 18:38:55 -04002539
René Scharfe70c49052017-06-24 16:09:39 +02002540 if (subdir_nr > 0xff)
2541 BUG("invalid loose object subdirectory: %x", subdir_nr);
2542
René Scharfe0375f472017-06-24 14:12:30 +02002543 origlen = path->len;
2544 strbuf_complete(path, '/');
2545 strbuf_addf(path, "%02x", subdir_nr);
René Scharfe0375f472017-06-24 14:12:30 +02002546
2547 dir = opendir(path->buf);
Jeff King27e1e222014-10-15 18:38:55 -04002548 if (!dir) {
René Scharfe0375f472017-06-24 14:12:30 +02002549 if (errno != ENOENT)
Nguyễn Thái Ngọc Duy259328b2018-07-21 09:49:39 +02002550 r = error_errno(_("unable to open %s"), path->buf);
René Scharfe0375f472017-06-24 14:12:30 +02002551 strbuf_setlen(path, origlen);
2552 return r;
Jeff King27e1e222014-10-15 18:38:55 -04002553 }
2554
René Scharfe62a24c82017-10-31 14:50:06 +01002555 oid.hash[0] = subdir_nr;
Derrick Stolee163ee5e2017-12-04 09:06:03 -05002556 strbuf_addch(path, '/');
2557 baselen = path->len;
René Scharfe62a24c82017-10-31 14:50:06 +01002558
Elijah Newrenb548f0f2021-05-12 17:28:22 +00002559 while ((de = readdir_skip_dot_and_dotdot(dir))) {
Derrick Stolee163ee5e2017-12-04 09:06:03 -05002560 size_t namelen;
Jeff King27e1e222014-10-15 18:38:55 -04002561
Derrick Stolee163ee5e2017-12-04 09:06:03 -05002562 namelen = strlen(de->d_name);
Jeff King27e1e222014-10-15 18:38:55 -04002563 strbuf_setlen(path, baselen);
Derrick Stolee163ee5e2017-12-04 09:06:03 -05002564 strbuf_add(path, de->d_name, namelen);
brian m. carlson94b5e092018-07-16 01:28:07 +00002565 if (namelen == the_hash_algo->hexsz - 2 &&
René Scharfe62a24c82017-10-31 14:50:06 +01002566 !hex_to_bytes(oid.hash + 1, de->d_name,
brian m. carlson94b5e092018-07-16 01:28:07 +00002567 the_hash_algo->rawsz - 1)) {
brian m. carlson5a6dce72021-04-26 01:02:55 +00002568 oid_set_algo(&oid, the_hash_algo);
René Scharfe62a24c82017-10-31 14:50:06 +01002569 if (obj_cb) {
2570 r = obj_cb(&oid, path->buf, data);
2571 if (r)
2572 break;
Jeff King27e1e222014-10-15 18:38:55 -04002573 }
René Scharfe62a24c82017-10-31 14:50:06 +01002574 continue;
Jeff King27e1e222014-10-15 18:38:55 -04002575 }
2576
2577 if (cruft_cb) {
2578 r = cruft_cb(de->d_name, path->buf, data);
2579 if (r)
2580 break;
2581 }
2582 }
Johannes Sixt094c7e62015-08-12 19:43:01 +02002583 closedir(dir);
Jeff King27e1e222014-10-15 18:38:55 -04002584
Derrick Stolee163ee5e2017-12-04 09:06:03 -05002585 strbuf_setlen(path, baselen - 1);
Jeff King27e1e222014-10-15 18:38:55 -04002586 if (!r && subdir_cb)
2587 r = subdir_cb(subdir_nr, path->buf, data);
2588
René Scharfe0375f472017-06-24 14:12:30 +02002589 strbuf_setlen(path, origlen);
2590
Jeff King27e1e222014-10-15 18:38:55 -04002591 return r;
2592}
2593
Jeff Kinge6f875e2015-02-08 20:13:22 -05002594int for_each_loose_file_in_objdir_buf(struct strbuf *path,
Jeff King27e1e222014-10-15 18:38:55 -04002595 each_loose_object_fn obj_cb,
2596 each_loose_cruft_fn cruft_cb,
2597 each_loose_subdir_fn subdir_cb,
2598 void *data)
2599{
Jeff King27e1e222014-10-15 18:38:55 -04002600 int r = 0;
2601 int i;
2602
Jeff King27e1e222014-10-15 18:38:55 -04002603 for (i = 0; i < 256; i++) {
Jeff Kinge6f875e2015-02-08 20:13:22 -05002604 r = for_each_file_in_obj_subdir(i, path, obj_cb, cruft_cb,
Jeff King27e1e222014-10-15 18:38:55 -04002605 subdir_cb, data);
Jeff King27e1e222014-10-15 18:38:55 -04002606 if (r)
2607 break;
2608 }
2609
Jeff Kinge6f875e2015-02-08 20:13:22 -05002610 return r;
2611}
2612
2613int for_each_loose_file_in_objdir(const char *path,
2614 each_loose_object_fn obj_cb,
2615 each_loose_cruft_fn cruft_cb,
2616 each_loose_subdir_fn subdir_cb,
2617 void *data)
2618{
2619 struct strbuf buf = STRBUF_INIT;
2620 int r;
2621
2622 strbuf_addstr(&buf, path);
2623 r = for_each_loose_file_in_objdir_buf(&buf, obj_cb, cruft_cb,
2624 subdir_cb, data);
Jeff King27e1e222014-10-15 18:38:55 -04002625 strbuf_release(&buf);
Jeff Kinge6f875e2015-02-08 20:13:22 -05002626
Jeff King27e1e222014-10-15 18:38:55 -04002627 return r;
2628}
Jeff King660c8892014-10-15 18:41:21 -04002629
Jeff Kinga7ff6f52018-08-10 19:09:44 -04002630int for_each_loose_object(each_loose_object_fn cb, void *data,
2631 enum for_each_object_flags flags)
Jeff King660c8892014-10-15 18:41:21 -04002632{
Jeff Kingf0eaf632018-11-12 09:50:39 -05002633 struct object_directory *odb;
Jeff King660c8892014-10-15 18:41:21 -04002634
Jeff Kingf0eaf632018-11-12 09:50:39 -05002635 prepare_alt_odb(the_repository);
2636 for (odb = the_repository->objects->odb; odb; odb = odb->next) {
2637 int r = for_each_loose_file_in_objdir(odb->path, cb, NULL,
2638 NULL, data);
2639 if (r)
2640 return r;
Jeff King660c8892014-10-15 18:41:21 -04002641
Jeff Kingf0eaf632018-11-12 09:50:39 -05002642 if (flags & FOR_EACH_OBJECT_LOCAL_ONLY)
2643 break;
2644 }
Jeff King1385bb72015-03-27 07:32:41 -04002645
Jeff Kingf0eaf632018-11-12 09:50:39 -05002646 return 0;
Jeff King660c8892014-10-15 18:41:21 -04002647}
2648
Jeff Kingbe252d32023-02-24 01:39:24 -05002649static int append_loose_object(const struct object_id *oid,
2650 const char *path UNUSED,
Jeff King3a2e0822018-11-12 09:50:56 -05002651 void *data)
2652{
Eric Wong92d8ed82021-07-07 23:10:19 +00002653 oidtree_insert(data, oid);
Jeff King3a2e0822018-11-12 09:50:56 -05002654 return 0;
2655}
2656
Eric Wong92d8ed82021-07-07 23:10:19 +00002657struct oidtree *odb_loose_cache(struct object_directory *odb,
René Scharfe0000d652019-01-06 17:45:30 +01002658 const struct object_id *oid)
2659{
2660 int subdir_nr = oid->hash[0];
Jeff King3a2e0822018-11-12 09:50:56 -05002661 struct strbuf buf = STRBUF_INIT;
Eric Wong33f379e2021-07-07 23:10:17 +00002662 size_t word_bits = bitsizeof(odb->loose_objects_subdir_seen[0]);
2663 size_t word_index = subdir_nr / word_bits;
Philip Oakley26de1fc2021-12-01 00:29:02 +00002664 size_t mask = (size_t)1u << (subdir_nr % word_bits);
Eric Wong33f379e2021-07-07 23:10:17 +00002665 uint32_t *bitmap;
Jeff King3a2e0822018-11-12 09:50:56 -05002666
2667 if (subdir_nr < 0 ||
Eric Wong33f379e2021-07-07 23:10:17 +00002668 subdir_nr >= bitsizeof(odb->loose_objects_subdir_seen))
Jeff King3a2e0822018-11-12 09:50:56 -05002669 BUG("subdir_nr out of range");
2670
Eric Wong33f379e2021-07-07 23:10:17 +00002671 bitmap = &odb->loose_objects_subdir_seen[word_index];
2672 if (*bitmap & mask)
Eric Wong92d8ed82021-07-07 23:10:19 +00002673 return odb->loose_objects_cache;
2674 if (!odb->loose_objects_cache) {
2675 ALLOC_ARRAY(odb->loose_objects_cache, 1);
2676 oidtree_init(odb->loose_objects_cache);
2677 }
Jeff King3a2e0822018-11-12 09:50:56 -05002678 strbuf_addstr(&buf, odb->path);
2679 for_each_file_in_obj_subdir(subdir_nr, &buf,
2680 append_loose_object,
2681 NULL, NULL,
Eric Wong92d8ed82021-07-07 23:10:19 +00002682 odb->loose_objects_cache);
Eric Wong33f379e2021-07-07 23:10:17 +00002683 *bitmap |= mask;
Jeff King7317aa72018-11-22 12:53:00 -05002684 strbuf_release(&buf);
Eric Wong92d8ed82021-07-07 23:10:19 +00002685 return odb->loose_objects_cache;
Jeff King660c8892014-10-15 18:41:21 -04002686}
2687
René Scharfed4e19e52019-01-06 17:45:39 +01002688void odb_clear_loose_cache(struct object_directory *odb)
2689{
Eric Wong92d8ed82021-07-07 23:10:19 +00002690 oidtree_clear(odb->loose_objects_cache);
2691 FREE_AND_NULL(odb->loose_objects_cache);
René Scharfed4e19e52019-01-06 17:45:39 +01002692 memset(&odb->loose_objects_subdir_seen, 0,
2693 sizeof(odb->loose_objects_subdir_seen));
2694}
2695
Jeff King00a77602019-01-07 03:37:02 -05002696static int check_stream_oid(git_zstream *stream,
2697 const char *hdr,
2698 unsigned long size,
2699 const char *path,
2700 const struct object_id *expected_oid)
Jeff Kingf6371f92017-01-13 12:58:16 -05002701{
brian m. carlson18e25882018-02-01 02:18:41 +00002702 git_hash_ctx c;
Jeff King00a77602019-01-07 03:37:02 -05002703 struct object_id real_oid;
Jeff Kingf6371f92017-01-13 12:58:16 -05002704 unsigned char buf[4096];
2705 unsigned long total_read;
2706 int status = Z_OK;
2707
brian m. carlson18e25882018-02-01 02:18:41 +00002708 the_hash_algo->init_fn(&c);
2709 the_hash_algo->update_fn(&c, hdr, stream->total_out);
Jeff Kingf6371f92017-01-13 12:58:16 -05002710
2711 /*
2712 * We already read some bytes into hdr, but the ones up to the NUL
2713 * do not count against the object's content size.
2714 */
2715 total_read = stream->total_out - strlen(hdr) - 1;
2716
2717 /*
2718 * This size comparison must be "<=" to read the final zlib packets;
Jeff King00a77602019-01-07 03:37:02 -05002719 * see the comment in unpack_loose_rest for details.
Jeff Kingf6371f92017-01-13 12:58:16 -05002720 */
2721 while (total_read <= size &&
Junio C Hamano18ad13e2018-10-31 13:12:12 +09002722 (status == Z_OK ||
2723 (status == Z_BUF_ERROR && !stream->avail_out))) {
Jeff Kingf6371f92017-01-13 12:58:16 -05002724 stream->next_out = buf;
2725 stream->avail_out = sizeof(buf);
2726 if (size - total_read < stream->avail_out)
2727 stream->avail_out = size - total_read;
2728 status = git_inflate(stream, Z_FINISH);
brian m. carlson18e25882018-02-01 02:18:41 +00002729 the_hash_algo->update_fn(&c, buf, stream->next_out - buf);
Jeff Kingf6371f92017-01-13 12:58:16 -05002730 total_read += stream->next_out - buf;
2731 }
2732 git_inflate_end(stream);
2733
2734 if (status != Z_STREAM_END) {
Jeff King00a77602019-01-07 03:37:02 -05002735 error(_("corrupt loose object '%s'"), oid_to_hex(expected_oid));
Jeff Kingf6371f92017-01-13 12:58:16 -05002736 return -1;
2737 }
Jeff Kingcce044d2017-01-13 13:00:25 -05002738 if (stream->avail_in) {
Nguyễn Thái Ngọc Duy259328b2018-07-21 09:49:39 +02002739 error(_("garbage at end of loose object '%s'"),
Jeff King00a77602019-01-07 03:37:02 -05002740 oid_to_hex(expected_oid));
Jeff Kingcce044d2017-01-13 13:00:25 -05002741 return -1;
2742 }
Jeff Kingf6371f92017-01-13 12:58:16 -05002743
brian m. carlson5951bf42021-04-26 01:02:53 +00002744 the_hash_algo->final_oid_fn(&real_oid, &c);
Jeff King00a77602019-01-07 03:37:02 -05002745 if (!oideq(expected_oid, &real_oid)) {
Jeff King01f8d592019-01-07 03:40:34 -05002746 error(_("hash mismatch for %s (expected %s)"), path,
Jeff King00a77602019-01-07 03:37:02 -05002747 oid_to_hex(expected_oid));
Jeff Kingf6371f92017-01-13 12:58:16 -05002748 return -1;
2749 }
2750
2751 return 0;
2752}
2753
2754int read_loose_object(const char *path,
brian m. carlsond61d87b2018-03-12 02:27:38 +00002755 const struct object_id *expected_oid,
Ævar Arnfjörð Bjarmason96e41f52021-10-01 11:16:53 +02002756 struct object_id *real_oid,
Ævar Arnfjörð Bjarmason31deb282021-10-01 11:16:52 +02002757 void **contents,
2758 struct object_info *oi)
Jeff Kingf6371f92017-01-13 12:58:16 -05002759{
2760 int ret = -1;
Jonathan Tanae285ac2022-12-14 11:17:41 -08002761 int fd;
Jeff Kingf6371f92017-01-13 12:58:16 -05002762 void *map = NULL;
2763 unsigned long mapsize;
2764 git_zstream stream;
brian m. carlson1af64f72018-03-12 02:27:55 +00002765 char hdr[MAX_HEADER_LEN];
Ævar Arnfjörð Bjarmason31deb282021-10-01 11:16:52 +02002766 unsigned long *size = oi->sizep;
Jeff Kingf6371f92017-01-13 12:58:16 -05002767
Jonathan Tanae285ac2022-12-14 11:17:41 -08002768 fd = git_open(path);
2769 if (fd >= 0)
2770 map = map_fd(fd, path, &mapsize);
Jeff Kingf6371f92017-01-13 12:58:16 -05002771 if (!map) {
Nguyễn Thái Ngọc Duy259328b2018-07-21 09:49:39 +02002772 error_errno(_("unable to mmap %s"), path);
Jeff Kingf6371f92017-01-13 12:58:16 -05002773 goto out;
2774 }
2775
Derrick Stolee8a505712022-05-16 10:53:27 -04002776 if (unpack_loose_header(&stream, map, mapsize, hdr, sizeof(hdr),
2777 NULL) != ULHR_OK) {
Nguyễn Thái Ngọc Duy259328b2018-07-21 09:49:39 +02002778 error(_("unable to unpack header of %s"), path);
Jeff Kingf6371f92017-01-13 12:58:16 -05002779 goto out;
2780 }
2781
Ævar Arnfjörð Bjarmason31deb282021-10-01 11:16:52 +02002782 if (parse_loose_header(hdr, oi) < 0) {
Nguyễn Thái Ngọc Duy259328b2018-07-21 09:49:39 +02002783 error(_("unable to parse header of %s"), path);
Jeff Kingf6371f92017-01-13 12:58:16 -05002784 git_inflate_end(&stream);
2785 goto out;
2786 }
2787
Ævar Arnfjörð Bjarmason31deb282021-10-01 11:16:52 +02002788 if (*oi->typep == OBJ_BLOB && *size > big_file_threshold) {
Jeff King00a77602019-01-07 03:37:02 -05002789 if (check_stream_oid(&stream, hdr, *size, path, expected_oid) < 0)
Jeff Kingf6371f92017-01-13 12:58:16 -05002790 goto out;
2791 } else {
Jeff King00a77602019-01-07 03:37:02 -05002792 *contents = unpack_loose_rest(&stream, hdr, *size, expected_oid);
Jeff Kingf6371f92017-01-13 12:58:16 -05002793 if (!*contents) {
Nguyễn Thái Ngọc Duy259328b2018-07-21 09:49:39 +02002794 error(_("unable to unpack contents of %s"), path);
Jeff Kingf6371f92017-01-13 12:58:16 -05002795 git_inflate_end(&stream);
2796 goto out;
2797 }
Ævar Arnfjörð Bjarmason44439c12022-02-05 00:48:32 +01002798 hash_object_file_literally(the_repository->hash_algo,
Ævar Arnfjörð Bjarmason16235e32021-11-11 06:18:56 +01002799 *contents, *size,
Ævar Arnfjörð Bjarmason44439c12022-02-05 00:48:32 +01002800 oi->type_name->buf, real_oid);
Ævar Arnfjörð Bjarmason0f156db2022-02-05 00:48:30 +01002801 if (!oideq(expected_oid, real_oid))
Jeff Kingf6371f92017-01-13 12:58:16 -05002802 goto out;
Jeff Kingf6371f92017-01-13 12:58:16 -05002803 }
2804
2805 ret = 0; /* everything checks out */
2806
2807out:
2808 if (map)
2809 munmap(map, mapsize);
Jeff Kingf6371f92017-01-13 12:58:16 -05002810 return ret;
2811}