Coverage Report

Created: 2026-11-12 06:03

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/git/odb.c
Line
Count
Source
1
#include "git-compat-util.h"
2
#include "abspath.h"
3
#include "commit-graph.h"
4
#include "config.h"
5
#include "environment.h"
6
#include "gettext.h"
7
#include "hashmap.h"
8
#include "hex.h"
9
#include "lockfile.h"
10
#include "loose.h"
11
#include "midx.h"
12
#include "object-file-convert.h"
13
#include "object-file.h"
14
#include "object-name.h"
15
#include "odb.h"
16
#include "odb/source-files.h"
17
#include "odb/source-inmemory.h"
18
#include "path.h"
19
#include "promisor-remote.h"
20
#include "replace-object.h"
21
#include "run-command.h"
22
#include "setup.h"
23
#include "strbuf.h"
24
#include "strvec.h"
25
#include "submodule.h"
26
#include "tmp-objdir.h"
27
#include "trace2.h"
28
#include "write-or-die.h"
29
30
static const char * const object_storage_name_by_format[] = {
31
  [OBJECT_STORAGE_FORMAT_UNKNOWN] = "unknown",
32
  [OBJECT_STORAGE_FORMAT_FILES] = "files",
33
};
34
35
enum object_storage_format object_storage_format_by_name(const char *name)
36
0
{
37
0
  for (size_t i = 0; i < ARRAY_SIZE(object_storage_name_by_format); i++)
38
0
    if (!strcmp(object_storage_name_by_format[i], name))
39
0
      return i;
40
0
  return OBJECT_STORAGE_FORMAT_UNKNOWN;
41
0
}
42
43
const char *object_storage_format_to_name(enum object_storage_format format)
44
0
{
45
0
  if (format < 0 || format >= ARRAY_SIZE(object_storage_name_by_format))
46
0
    format = OBJECT_STORAGE_FORMAT_UNKNOWN;
47
0
  return object_storage_name_by_format[format];
48
0
}
49
50
enum object_storage_format object_storage_format_by_uri(const char *uri, char **payload)
51
0
{
52
0
  enum object_storage_format format;
53
0
  const char *schema_end;
54
0
  char *name;
55
56
0
  schema_end = strstr(uri, "://");
57
0
  if (!schema_end) {
58
0
    name = xstrdup(uri);
59
0
    if (payload)
60
0
      *payload = NULL;
61
0
  } else {
62
0
    name = xstrndup(uri, schema_end - uri);
63
0
    if (payload)
64
0
      *payload = *(schema_end + 3) ? xstrdup(schema_end + 3) : NULL;
65
0
  }
66
67
0
  format = object_storage_format_by_name(name);
68
69
0
  free(name);
70
0
  return format;
71
0
}
72
73
int odb_mkstemp(struct object_database *odb,
74
    struct strbuf *temp_filename, const char *pattern)
75
0
{
76
0
  int fd;
77
  /*
78
   * we let the umask do its job, don't try to be more
79
   * restrictive except to remove write permission.
80
   */
81
0
  int mode = 0444;
82
0
  repo_git_path_replace(odb->repo, temp_filename, "objects/%s", pattern);
83
0
  fd = git_mkstemp_mode(temp_filename->buf, mode);
84
0
  if (0 <= fd)
85
0
    return fd;
86
87
  /* slow path */
88
  /* some mkstemp implementations erase temp_filename on failure */
89
0
  repo_git_path_replace(odb->repo, temp_filename, "objects/%s", pattern);
90
0
  safe_create_leading_directories(odb->repo, temp_filename->buf);
91
0
  return xmkstemp_mode(temp_filename->buf, mode);
92
0
}
93
94
char *compute_alternate_path(const char *path, struct strbuf *err)
95
0
{
96
0
  char *ref_git = NULL;
97
0
  const char *repo;
98
0
  int seen_error = 0;
99
100
0
  ref_git = real_pathdup(path, 0);
101
0
  if (!ref_git) {
102
0
    seen_error = 1;
103
0
    strbuf_addf(err, _("path '%s' does not exist"), path);
104
0
    goto out;
105
0
  }
106
107
0
  repo = read_gitfile(ref_git);
108
0
  if (!repo)
109
0
    repo = read_gitfile(mkpath("%s/.git", ref_git));
110
0
  if (repo) {
111
0
    free(ref_git);
112
0
    ref_git = xstrdup(repo);
113
0
  }
114
115
0
  if (!repo && is_directory(mkpath("%s/.git/objects", ref_git))) {
116
0
    char *ref_git_git = mkpathdup("%s/.git", ref_git);
117
0
    free(ref_git);
118
0
    ref_git = ref_git_git;
119
0
  } else if (!is_directory(mkpath("%s/objects", ref_git))) {
120
0
    struct strbuf sb = STRBUF_INIT;
121
0
    seen_error = 1;
122
0
    if (get_common_dir(&sb, ref_git)) {
123
0
      strbuf_addf(err,
124
0
            _("reference repository '%s' as a linked "
125
0
              "checkout is not supported yet."),
126
0
            path);
127
0
      goto out;
128
0
    }
129
130
0
    strbuf_addf(err, _("reference repository '%s' is not a "
131
0
          "local repository."), path);
132
0
    goto out;
133
0
  }
134
135
0
  if (!access(mkpath("%s/shallow", ref_git), F_OK)) {
136
0
    strbuf_addf(err, _("reference repository '%s' is shallow"),
137
0
          path);
138
0
    seen_error = 1;
139
0
    goto out;
140
0
  }
141
142
0
  if (!access(mkpath("%s/info/grafts", ref_git), F_OK)) {
143
0
    strbuf_addf(err,
144
0
          _("reference repository '%s' is grafted"),
145
0
          path);
146
0
    seen_error = 1;
147
0
    goto out;
148
0
  }
149
150
0
out:
151
0
  if (seen_error) {
152
0
    FREE_AND_NULL(ref_git);
153
0
  }
154
155
0
  return ref_git;
156
0
}
157
158
static void fill_alternate_refs_command(struct repository *repo,
159
          struct child_process *cmd,
160
          const char *repo_path)
161
0
{
162
0
  const char *value;
163
164
0
  if (!repo_config_get_value(repo, "core.alternateRefsCommand", &value)) {
165
0
    cmd->use_shell = 1;
166
167
0
    strvec_push(&cmd->args, value);
168
0
    strvec_push(&cmd->args, repo_path);
169
0
  } else {
170
0
    cmd->git_cmd = 1;
171
172
0
    strvec_pushf(&cmd->args, "--git-dir=%s", repo_path);
173
0
    strvec_push(&cmd->args, "for-each-ref");
174
0
    strvec_push(&cmd->args, "--format=%(objectname)");
175
176
0
    if (!repo_config_get_value(repo, "core.alternateRefsPrefixes", &value)) {
177
0
      strvec_push(&cmd->args, "--");
178
0
      strvec_split(&cmd->args, value);
179
0
    }
180
0
  }
181
182
0
  strvec_pushv(&cmd->env, (const char **)local_repo_env);
183
0
  cmd->out = -1;
184
0
}
185
186
static void read_alternate_refs(struct repository *repo,
187
        const char *path,
188
        odb_for_each_alternate_ref_fn *cb,
189
        void *payload)
190
0
{
191
0
  struct child_process cmd = CHILD_PROCESS_INIT;
192
0
  struct strbuf line = STRBUF_INIT;
193
0
  FILE *fh;
194
195
0
  fill_alternate_refs_command(repo, &cmd, path);
196
197
0
  if (start_command(&cmd))
198
0
    return;
199
200
0
  fh = xfdopen(cmd.out, "r");
201
0
  while (strbuf_getline_lf(&line, fh) != EOF) {
202
0
    struct object_id oid;
203
0
    const char *p;
204
205
0
    if (parse_oid_hex_algop(line.buf, &oid, &p, repo->hash_algo) || *p) {
206
0
      warning(_("invalid line while parsing alternate refs: %s"),
207
0
        line.buf);
208
0
      break;
209
0
    }
210
211
0
    cb(&oid, payload);
212
0
  }
213
214
0
  fclose(fh);
215
0
  finish_command(&cmd);
216
0
  strbuf_release(&line);
217
0
}
218
219
struct alternate_refs_data {
220
  struct repository *repo;
221
  odb_for_each_alternate_ref_fn *fn;
222
  void *payload;
223
};
224
225
static int refs_from_alternate_cb(struct odb_files_dir *alternate,
226
          void *payload)
227
0
{
228
0
  struct strbuf path = STRBUF_INIT;
229
0
  size_t base_len;
230
0
  struct alternate_refs_data *cb = payload;
231
232
0
  if (!strbuf_realpath(&path, alternate->abspath, 0))
233
0
    goto out;
234
0
  if (!strbuf_strip_suffix(&path, "/objects"))
235
0
    goto out;
236
0
  base_len = path.len;
237
238
  /* Is this a git repository with refs? */
239
0
  strbuf_addstr(&path, "/refs");
240
0
  if (!is_directory(path.buf))
241
0
    goto out;
242
0
  strbuf_setlen(&path, base_len);
243
244
  /* A shallow or grafted repository may lack the history behind its refs. */
245
0
  strbuf_addstr(&path, "/shallow");
246
0
  if (!access(path.buf, F_OK))
247
0
    goto out;
248
0
  strbuf_setlen(&path, base_len);
249
250
0
  strbuf_addstr(&path, "/info/grafts");
251
0
  if (!access(path.buf, F_OK))
252
0
    goto out;
253
0
  strbuf_setlen(&path, base_len);
254
255
0
  read_alternate_refs(cb->repo, path.buf, cb->fn, cb->payload);
256
257
0
out:
258
0
  strbuf_release(&path);
259
0
  return 0;
260
0
}
261
262
void odb_for_each_alternate_ref(struct object_database *odb,
263
        odb_for_each_alternate_ref_fn cb, void *payload)
264
0
{
265
0
  struct alternate_refs_data data = {
266
0
    .fn = cb,
267
0
    .payload = payload,
268
0
    .repo = odb->repo,
269
0
  };
270
0
  odb_for_each_alternate(odb, refs_from_alternate_cb, &data);
271
0
}
272
273
int odb_for_each_alternate(struct object_database *odb,
274
       odb_for_each_alternate_fn cb, void *payload)
275
0
{
276
0
  struct odb_source_files *files = odb_source_files_downcast(odb->source);
277
0
  int r = 0;
278
279
0
  for (struct odb_files_dir *dir = files->dirs->next; dir; dir = dir->next) {
280
0
    r = cb(dir, payload);
281
0
    if (r)
282
0
      break;
283
0
  }
284
0
  return r;
285
0
}
286
287
int odb_has_alternates(struct object_database *odb)
288
0
{
289
0
  if (odb->source->type != ODB_SOURCE_FILES)
290
0
    return 0;
291
0
  return !!odb_source_files_downcast(odb->source)->dirs->next;
292
0
}
293
294
int obj_read_use_lock = 0;
295
pthread_mutex_t obj_read_mutex;
296
297
void enable_obj_read_lock(void)
298
0
{
299
0
  if (obj_read_use_lock)
300
0
    return;
301
302
0
  obj_read_use_lock = 1;
303
0
  init_recursive_mutex(&obj_read_mutex);
304
0
}
305
306
void disable_obj_read_lock(void)
307
0
{
308
0
  if (!obj_read_use_lock)
309
0
    return;
310
311
0
  obj_read_use_lock = 0;
312
0
  pthread_mutex_destroy(&obj_read_mutex);
313
0
}
314
315
static enum odb_read_status do_oid_object_info_extended(struct object_database *odb,
316
              const struct object_id *oid,
317
              struct object_info *oi, unsigned flags)
318
0
{
319
0
  struct strbuf corrupt_err = STRBUF_INIT;
320
0
  const struct object_id *real = oid;
321
0
  enum odb_read_status ret;
322
323
0
  if (flags & OBJECT_INFO_LOOKUP_REPLACE)
324
0
    real = lookup_replace_object(odb->repo, oid);
325
326
0
  if (is_null_oid(real))
327
0
    return -1;
328
329
0
  if (!odb_source_read_object_info(odb->inmemory_objects, oid, oi, flags, NULL))
330
0
    return 0;
331
332
0
  ret = odb_source_read_object_info(odb->source, real, oi, flags,
333
0
            &corrupt_err);
334
0
  if (ret == ODB_READ_NOT_FOUND &&
335
0
      odb->repo->fetch_if_missing &&
336
0
      !(flags & OBJECT_INFO_SKIP_FETCH_OBJECT) &&
337
0
      repo_has_promisor_remote(odb->repo)) {
338
    /* Try to fetch the missing object from a promisor remote. */
339
0
    promisor_remote_get_direct(odb->repo, real, 1);
340
0
    ret = odb_source_read_object_info(odb->source, real, oi, flags,
341
0
              &corrupt_err);
342
0
  }
343
344
0
  if (ret < 0 && (flags & OBJECT_INFO_DIE_IF_CORRUPT)) {
345
0
    if ((flags & OBJECT_INFO_LOOKUP_REPLACE) && !oideq(real, oid))
346
0
      die(_("replacement %s not found for %s"),
347
0
          oid_to_hex(real), oid_to_hex(oid));
348
0
    if (ret != ODB_READ_NOT_FOUND) {
349
0
      if (corrupt_err.len)
350
0
        die("%s", corrupt_err.buf);
351
0
      die(_("object %s is corrupt"), oid_to_hex(real));
352
0
    }
353
0
  }
354
355
0
  strbuf_release(&corrupt_err);
356
0
  return ret;
357
0
}
358
359
static int oid_object_info_convert(struct repository *r,
360
           const struct object_id *input_oid,
361
           struct object_info *input_oi, unsigned flags)
362
0
{
363
0
  const struct git_hash_algo *input_algo = &hash_algos[input_oid->algo];
364
0
  int do_die = flags & OBJECT_INFO_DIE_IF_CORRUPT;
365
0
  enum object_type type;
366
0
  struct object_id oid, delta_base_oid;
367
0
  struct object_info new_oi, *oi;
368
0
  size_t size;
369
0
  void *content;
370
0
  int ret;
371
372
0
  if (repo_oid_to_algop(r, input_oid, r->hash_algo, &oid)) {
373
0
    if (do_die)
374
0
      die(_("missing mapping of %s to %s"),
375
0
          oid_to_hex(input_oid), r->hash_algo->name);
376
0
    return -1;
377
0
  }
378
379
  /* Is new_oi needed? */
380
0
  oi = input_oi;
381
0
  if (input_oi && (input_oi->delta_base_oid || input_oi->sizep ||
382
0
       input_oi->contentp)) {
383
0
    new_oi = *input_oi;
384
    /* Does delta_base_oid need to be converted? */
385
0
    if (input_oi->delta_base_oid)
386
0
      new_oi.delta_base_oid = &delta_base_oid;
387
    /* Will the attributes differ when converted? */
388
0
    if (input_oi->sizep || input_oi->contentp) {
389
0
      new_oi.contentp = &content;
390
0
      new_oi.sizep = &size;
391
0
      new_oi.typep = &type;
392
0
    }
393
0
    oi = &new_oi;
394
0
  }
395
396
0
  ret = odb_read_object_info_extended(r->objects, &oid, oi, flags);
397
0
  if (ret)
398
0
    return -1;
399
0
  if (oi == input_oi)
400
0
    return ret;
401
402
0
  if (new_oi.contentp) {
403
0
    struct strbuf outbuf = STRBUF_INIT;
404
405
0
    if (type != OBJ_BLOB) {
406
0
      ret = convert_object_file(r, &outbuf,
407
0
              r->hash_algo, input_algo,
408
0
              content, size, type, !do_die);
409
0
      free(content);
410
0
      if (ret == -1)
411
0
        return -1;
412
0
      size = outbuf.len;
413
0
      content = strbuf_detach(&outbuf, NULL);
414
0
    }
415
0
    if (input_oi->sizep)
416
0
      *input_oi->sizep = size;
417
0
    if (input_oi->contentp)
418
0
      *input_oi->contentp = content;
419
0
    else
420
0
      free(content);
421
0
    if (input_oi->typep)
422
0
      *input_oi->typep = type;
423
0
  }
424
0
  if (new_oi.delta_base_oid == &delta_base_oid) {
425
0
    if (repo_oid_to_algop(r, &delta_base_oid, input_algo,
426
0
         input_oi->delta_base_oid)) {
427
0
      if (do_die)
428
0
        die(_("missing mapping of %s to %s"),
429
0
            oid_to_hex(&delta_base_oid),
430
0
            input_algo->name);
431
0
      return -1;
432
0
    }
433
0
  }
434
0
  if (input_oi->source_infop)
435
0
    *input_oi->source_infop = *new_oi.source_infop;
436
0
  return ret;
437
0
}
438
439
enum odb_read_status odb_read_object_info_extended(struct object_database *odb,
440
               const struct object_id *oid,
441
               struct object_info *oi,
442
               enum object_info_flags flags)
443
0
{
444
0
  enum odb_read_status ret;
445
446
0
  if (oid->algo && (hash_algo_by_ptr(odb->repo->hash_algo) != oid->algo))
447
0
    return oid_object_info_convert(odb->repo, oid, oi, flags);
448
449
0
  obj_read_lock();
450
0
  ret = do_oid_object_info_extended(odb, oid, oi, flags);
451
0
  obj_read_unlock();
452
0
  return ret;
453
0
}
454
455
456
/* returns enum object_type or negative */
457
int odb_read_object_info(struct object_database *odb,
458
       const struct object_id *oid,
459
       size_t *sizep)
460
0
{
461
0
  enum object_type type;
462
0
  struct object_info oi = OBJECT_INFO_INIT;
463
464
0
  oi.typep = &type;
465
0
  oi.sizep = sizep;
466
0
  if (odb_read_object_info_extended(odb, oid, &oi,
467
0
            OBJECT_INFO_LOOKUP_REPLACE) < 0)
468
0
    return -1;
469
0
  return type;
470
0
}
471
472
int odb_pretend_object(struct object_database *odb,
473
           void *buf, size_t len, enum object_type type,
474
           struct object_id *oid)
475
0
{
476
0
  hash_object_file(odb->repo->hash_algo, buf, len, type, oid);
477
0
  if (odb_has_object(odb, oid, 0))
478
0
    return 0;
479
480
0
  return odb_source_write_object(odb->inmemory_objects,
481
0
               buf, len, type, oid, NULL, NULL, 0);
482
0
}
483
484
void *odb_read_object(struct object_database *odb,
485
          const struct object_id *oid,
486
          enum object_type *type,
487
          size_t *size)
488
0
{
489
0
  struct object_info oi = OBJECT_INFO_INIT;
490
0
  unsigned flags = OBJECT_INFO_DIE_IF_CORRUPT | OBJECT_INFO_LOOKUP_REPLACE;
491
0
  void *data;
492
493
0
  oi.typep = type;
494
0
  oi.sizep = size;
495
0
  oi.contentp = &data;
496
0
  if (odb_read_object_info_extended(odb, oid, &oi, flags))
497
0
    return NULL;
498
499
0
  return data;
500
0
}
501
502
void *odb_read_object_peeled(struct object_database *odb,
503
           const struct object_id *oid,
504
           enum object_type required_type,
505
           size_t *size,
506
           struct object_id *actual_oid_return)
507
0
{
508
0
  enum object_type type;
509
0
  void *buffer;
510
0
  size_t isize;
511
0
  struct object_id actual_oid;
512
513
0
  oidcpy(&actual_oid, oid);
514
0
  while (1) {
515
0
    int ref_length = -1;
516
0
    const char *ref_type = NULL;
517
518
0
    buffer = odb_read_object(odb, &actual_oid, &type, &isize);
519
0
    if (!buffer)
520
0
      return NULL;
521
0
    if (type == required_type) {
522
0
      *size = isize;
523
0
      if (actual_oid_return)
524
0
        oidcpy(actual_oid_return, &actual_oid);
525
0
      return buffer;
526
0
    }
527
    /* Handle references */
528
0
    else if (type == OBJ_COMMIT)
529
0
      ref_type = "tree ";
530
0
    else if (type == OBJ_TAG)
531
0
      ref_type = "object ";
532
0
    else {
533
0
      free(buffer);
534
0
      return NULL;
535
0
    }
536
0
    ref_length = strlen(ref_type);
537
538
0
    if (ref_length + odb->repo->hash_algo->hexsz > isize ||
539
0
        memcmp(buffer, ref_type, ref_length) ||
540
0
        get_oid_hex_algop((char *) buffer + ref_length, &actual_oid,
541
0
              odb->repo->hash_algo)) {
542
0
      free(buffer);
543
0
      return NULL;
544
0
    }
545
0
    free(buffer);
546
    /* Now we have the ID of the referred-to object in
547
     * actual_oid.  Check again. */
548
0
  }
549
0
}
550
551
int odb_has_object(struct object_database *odb, const struct object_id *oid,
552
       enum odb_has_object_flags flags)
553
0
{
554
0
  unsigned object_info_flags = 0;
555
556
0
  if (!startup_info->have_repository)
557
0
    return 0;
558
0
  if (!(flags & ODB_HAS_OBJECT_RECHECK_PACKED))
559
0
    object_info_flags |= OBJECT_INFO_QUICK;
560
0
  if (!(flags & ODB_HAS_OBJECT_FETCH_PROMISOR))
561
0
    object_info_flags |= OBJECT_INFO_SKIP_FETCH_OBJECT;
562
563
0
  return odb_read_object_info_extended(odb, oid, NULL, object_info_flags) >= 0;
564
0
}
565
566
int odb_freshen_object(struct object_database *odb,
567
           const struct object_id *oid)
568
0
{
569
0
  return odb_source_freshen_object(odb->source, oid, NULL);
570
0
}
571
572
int odb_for_each_object_ext(struct object_database *odb,
573
          const struct object_info *request,
574
          odb_for_each_object_cb cb,
575
          void *cb_data,
576
          const struct odb_for_each_object_options *opts)
577
0
{
578
0
  return odb_source_for_each_object(odb->source, request, cb, cb_data, opts);
579
0
}
580
581
int odb_for_each_object(struct object_database *odb,
582
      const struct object_info *request,
583
      odb_for_each_object_cb cb,
584
      void *cb_data,
585
      enum odb_for_each_object_flags flags)
586
0
{
587
0
  struct odb_for_each_object_options opts = {
588
0
    .flags = flags,
589
0
  };
590
0
  return odb_for_each_object_ext(odb, request, cb, cb_data, &opts);
591
0
}
592
593
int odb_count_objects(struct object_database *odb,
594
          enum odb_count_objects_flags flags,
595
          unsigned long *out)
596
0
{
597
0
  unsigned long count = 0;
598
0
  int ret;
599
600
0
  if (odb->object_count_valid && odb->object_count_flags == flags) {
601
0
    *out = odb->object_count;
602
0
    return 0;
603
0
  }
604
605
0
  ret = odb_source_count_objects(odb->source, flags, &count);
606
0
  if (ret < 0)
607
0
    goto out;
608
609
0
  odb->object_count = count;
610
0
  odb->object_count_valid = 1;
611
0
  odb->object_count_flags = flags;
612
613
0
  *out = count;
614
0
  ret = 0;
615
616
0
out:
617
0
  return ret;
618
0
}
619
620
/*
621
 * Return the slot of the most-significant bit set in "val". There are various
622
 * ways to do this quickly with fls() or __builtin_clzl(), but speed is
623
 * probably not a big deal here.
624
 */
625
static unsigned msb(unsigned long val)
626
0
{
627
0
  unsigned r = 0;
628
0
  while (val >>= 1)
629
0
    r++;
630
0
  return r;
631
0
}
632
633
int odb_find_abbrev_len(struct object_database *odb,
634
      const struct object_id *oid,
635
      int min_length,
636
      unsigned *out)
637
0
{
638
0
  const struct git_hash_algo *algo =
639
0
    oid->algo ? &hash_algos[oid->algo] : odb->repo->hash_algo;
640
0
  const unsigned hexsz = algo->hexsz;
641
0
  unsigned len;
642
0
  int ret;
643
644
0
  if (min_length < 0) {
645
0
    unsigned long count;
646
647
0
    if (odb_count_objects(odb, ODB_COUNT_OBJECTS_APPROXIMATE, &count) < 0)
648
0
      count = 0;
649
650
    /*
651
     * Add one because the MSB only tells us the highest bit set,
652
     * not including the value of all the _other_ bits (so "15"
653
     * is only one off of 2^4, but the MSB is the 3rd bit.
654
     */
655
0
    len = msb(count) + 1;
656
    /*
657
     * We now know we have on the order of 2^len objects, which
658
     * expects a collision at 2^(len/2). But we also care about hex
659
     * chars, not bits, and there are 4 bits per hex. So all
660
     * together we need to divide by 2 and round up.
661
     */
662
0
    len = DIV_ROUND_UP(len, 2);
663
    /*
664
     * For very small repos, we stick with our regular fallback.
665
     */
666
0
    if (len < FALLBACK_DEFAULT_ABBREV)
667
0
      len = FALLBACK_DEFAULT_ABBREV;
668
0
  } else {
669
0
    len = min_length;
670
0
  }
671
672
0
  if (len >= hexsz || !len) {
673
0
    *out = hexsz;
674
0
    ret = 0;
675
0
    goto out;
676
0
  }
677
678
0
  ret = odb_source_find_abbrev_len(odb->source, oid, len, &len);
679
0
  *out = len;
680
681
0
out:
682
0
  return ret;
683
0
}
684
685
void odb_assert_oid_type(struct object_database *odb,
686
       const struct object_id *oid, enum object_type expect)
687
0
{
688
0
  enum object_type type = odb_read_object_info(odb, oid, NULL);
689
0
  if (type < 0)
690
0
    die(_("%s is not a valid object"), oid_to_hex(oid));
691
0
  if (type != expect)
692
0
    die(_("%s is not a valid '%s' object"), oid_to_hex(oid),
693
0
        type_name(expect));
694
0
}
695
696
int odb_write_object_ext(struct object_database *odb,
697
       const void *buf, unsigned long len,
698
       enum object_type type,
699
       struct object_id *oid,
700
       const struct object_id *compat_oid_in,
701
       enum odb_write_object_flags flags)
702
0
{
703
0
  const struct git_hash_algo *compat = odb->repo->compat_hash_algo;
704
0
  struct object_id compat_oid, *compat_oid_p = NULL;
705
706
0
  hash_object_file(odb->repo->hash_algo, buf, len, type, oid);
707
708
  /*
709
   * We can skip the write in case we already have the object available.
710
   * In that case, we only freshen its mtime.
711
   */
712
0
  if (odb_freshen_object(odb, oid))
713
0
    return 0;
714
715
0
  if (compat) {
716
0
    const struct git_hash_algo *algo = odb->repo->hash_algo;
717
718
0
    if (compat_oid_in) {
719
0
      oidcpy(&compat_oid, compat_oid_in);
720
0
    } else if (type == OBJ_BLOB) {
721
0
      hash_object_file(compat, buf, len, type, &compat_oid);
722
0
    } else {
723
0
      struct strbuf converted = STRBUF_INIT;
724
0
      convert_object_file(odb->repo, &converted, algo, compat,
725
0
              buf, len, type, 0);
726
0
      hash_object_file(compat, converted.buf, converted.len,
727
0
           type, &compat_oid);
728
0
      strbuf_release(&converted);
729
0
    }
730
731
0
    compat_oid_p = &compat_oid;
732
0
  }
733
734
0
  return odb_source_write_object(odb->source, buf, len, type,
735
0
               oid, compat_oid_p, NULL, flags);
736
0
}
737
738
int odb_write_object_stream(struct object_database *odb,
739
          struct odb_stream *stream,
740
          struct object_id *oid)
741
0
{
742
0
  return odb_source_write_object_stream(odb->source, stream, oid);
743
0
}
744
745
int odb_optimize(struct object_database *odb,
746
     const struct odb_optimize_options *opts)
747
0
{
748
0
  return odb_source_optimize(odb->source, opts);
749
0
}
750
751
bool odb_optimize_required(struct object_database *odb,
752
         const struct odb_optimize_options *opts)
753
0
{
754
0
  return odb_source_optimize_required(odb->source, opts);
755
0
}
756
757
void odb_generate_pack_options_release(struct odb_generate_pack_options *opts)
758
0
{
759
0
  oid_array_clear(&opts->wants);
760
0
  oid_array_clear(&opts->haves);
761
0
  oid_array_clear(&opts->shallows);
762
0
}
763
764
int odb_generate_pack(struct object_database *odb,
765
          struct odb_pack_generator **out,
766
          const struct odb_generate_pack_options *opts)
767
0
{
768
0
  if (!odb->source->generate_pack)
769
0
    return error(_("primary object source does not support generating packfiles"));
770
0
  return odb_source_generate_pack(odb->source, out, opts);
771
0
}
772
773
int odb_pack_generator_finish(struct odb_pack_generator *generator)
774
0
{
775
0
  return generator->finish(generator);
776
0
}
777
778
struct object_database *odb_new(struct repository *repo,
779
        enum odb_new_flags flags)
780
0
{
781
0
  struct object_database *o;
782
783
0
  CALLOC_ARRAY(o, 1);
784
0
  o->repo = repo;
785
0
  pthread_mutex_init(&o->replace_mutex, NULL);
786
787
0
  o->source = odb_source_new(o, repo->object_storage_format,
788
0
           repo->object_storage_payload, flags);
789
0
  o->inmemory_objects = &odb_source_inmemory_new(o)->base;
790
791
0
  return o;
792
0
}
793
794
void odb_close(struct object_database *o)
795
0
{
796
0
  odb_source_close(o->source);
797
0
  close_commit_graph(o);
798
0
}
799
800
static void odb_free_sources(struct object_database *o)
801
0
{
802
0
  odb_source_free(o->source);
803
0
  odb_source_free(o->inmemory_objects);
804
0
  o->inmemory_objects = NULL;
805
0
}
806
807
void odb_free(struct object_database *o)
808
566
{
809
566
  if (!o)
810
566
    return;
811
812
0
  oidmap_clear(&o->replace_map, 1);
813
0
  pthread_mutex_destroy(&o->replace_mutex);
814
815
0
  odb_close(o);
816
0
  odb_free_sources(o);
817
818
0
  free(o);
819
0
}
820
821
void odb_prepare(struct object_database *o, enum odb_prepare_flags flags)
822
0
{
823
0
  obj_read_lock();
824
825
0
  if (flags & ODB_PREPARE_FLUSH_CACHES)
826
0
    o->object_count_valid = 0;
827
828
0
  odb_source_prepare(o->source, flags);
829
830
0
  obj_read_unlock();
831
0
}
832
833
void odb_reprepare(struct object_database *o)
834
0
{
835
0
  odb_prepare(o, ODB_PREPARE_FLUSH_CACHES);
836
0
}
837
838
int odb_fsck(struct object_database *odb, struct odb_fsck_options *options)
839
0
{
840
0
  return odb_source_fsck(odb->source, options);
841
0
}