Coverage Report

Created: 2026-10-17 07:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/git/odb/source-files.c
Line
Count
Source
1
#include "git-compat-util.h"
2
#include "abspath.h"
3
#include "blob.h"
4
#include "chdir-notify.h"
5
#include "config.h"
6
#include "gettext.h"
7
#include "hex.h"
8
#include "lockfile.h"
9
#include "object-file.h"
10
#include "odb.h"
11
#include "odb/source.h"
12
#include "odb/source-files.h"
13
#include "odb/source-loose.h"
14
#include "pack-objects.h"
15
#include "packfile.h"
16
#include "path.h"
17
#include "promisor-remote.h"
18
#include "repack.h"
19
#include "run-command.h"
20
#include "strbuf.h"
21
#include "string-list.h"
22
#include "strmap.h"
23
#include "strvec.h"
24
#include "tree.h"
25
#include "write-or-die.h"
26
27
static void odb_source_files_reparent(const char *old_cwd,
28
              const char *new_cwd,
29
              void *cb_data)
30
0
{
31
0
  struct odb_source_files *files = cb_data;
32
0
  char *path = reparent_relative_path(old_cwd, new_cwd,
33
0
              files->base.path);
34
0
  free(files->base.path);
35
0
  files->base.path = path;
36
0
}
37
38
static void odb_source_files_free(struct odb_source *source)
39
0
{
40
0
  struct odb_source_files *files = odb_source_files_downcast(source);
41
0
  chdir_notify_unregister(odb_source_files_reparent, files);
42
0
  odb_source_free(&files->loose->base);
43
0
  odb_source_free(&files->packed->base);
44
0
  odb_source_release(&files->base);
45
0
  free(files);
46
0
}
47
48
static void odb_source_files_close(struct odb_source *source)
49
0
{
50
0
  struct odb_source_files *files = odb_source_files_downcast(source);
51
0
  odb_source_close(&files->loose->base);
52
0
  odb_source_close(&files->packed->base);
53
0
}
54
55
static int odb_source_files_create_on_disk(struct odb_source *source,
56
             const struct odb_create_on_disk_options *opts)
57
0
{
58
0
  struct lock_file alternates_lock = LOCK_INIT;
59
0
  struct strbuf path = STRBUF_INIT;
60
0
  struct strset seen = STRSET_INIT;
61
0
  struct strbuf line = STRBUF_INIT;
62
0
  int ret;
63
64
0
  safe_create_dir(source->odb->repo, source->path, 1);
65
66
0
  strbuf_addf(&path, "%s/pack", source->path);
67
0
  safe_create_dir(source->odb->repo, path.buf, 1);
68
69
0
  strbuf_reset(&path);
70
0
  strbuf_addf(&path, "%s/info", source->path);
71
0
  safe_create_dir(source->odb->repo, path.buf, 1);
72
73
0
  if (opts->alternates && opts->alternates->nr) {
74
0
    FILE *alternates, *orig;
75
76
0
    strbuf_reset(&path);
77
0
    strbuf_addf(&path, "%s/info/alternates", source->path);
78
79
0
    repo_hold_lock_file_for_update(source->odb->repo, &alternates_lock,
80
0
                 path.buf, LOCK_DIE_ON_ERROR);
81
82
0
    alternates = fdopen_lock_file(&alternates_lock, "w");
83
0
    if (!alternates) {
84
0
      ret = error_errno(_("unable to fdopen alternates lockfile"));
85
0
      goto out;
86
0
    }
87
88
    /*
89
     * The alternates file may already exist, e.g. when it has been
90
     * seeded from a template directory. Read any preexisting
91
     * entries so that we don't end up writing duplicates.
92
     */
93
0
    orig = fopen(path.buf, "r");
94
0
    if (orig) {
95
0
      while (strbuf_getline(&line, orig) != EOF) {
96
0
        strset_add(&seen, line.buf);
97
0
        fprintf(alternates, "%s\n", line.buf);
98
0
      }
99
100
0
      if (ferror(orig)) {
101
0
        ret = error_errno(_("unable to read alternates file"));
102
0
        fclose(orig);
103
0
        goto out;
104
0
      }
105
106
0
      fclose(orig);
107
0
    } else if (errno != ENOENT) {
108
0
      ret = error_errno(_("unable to read alternates file"));
109
0
      goto out;
110
0
    }
111
112
0
    for (size_t i = 0; i < opts->alternates->nr; i++) {
113
0
      const char *alternate = opts->alternates->v[i];
114
0
      if (!strset_add(&seen, alternate))
115
0
        continue;
116
0
      fprintf(alternates, "%s\n", alternate);
117
0
    }
118
119
0
    if (ferror(alternates)) {
120
0
      ret = error_errno(_("unable to write alternates file"));
121
0
      goto out;
122
0
    }
123
124
0
    if (commit_lock_file(&alternates_lock)) {
125
0
      ret = error_errno(_("unable to commit alternates file"));
126
0
      goto out;
127
0
    }
128
0
  }
129
130
  /* Reprepare the object database to activate alternates. */
131
0
  odb_reprepare(source->odb);
132
133
0
  ret = 0;
134
135
0
out:
136
0
  rollback_lock_file(&alternates_lock);
137
0
  strbuf_release(&line);
138
0
  strbuf_release(&path);
139
0
  strset_clear(&seen);
140
0
  return ret;
141
0
}
142
143
static void odb_source_files_prepare(struct odb_source *source,
144
             enum odb_prepare_flags flags)
145
0
{
146
0
  struct odb_source_files *files = odb_source_files_downcast(source);
147
0
  odb_source_prepare(&files->loose->base, flags);
148
0
  odb_source_prepare(&files->packed->base, flags);
149
0
}
150
151
static enum odb_read_status odb_source_files_read_object_info(struct odb_source *source,
152
                    const struct object_id *oid,
153
                    struct object_info *oi,
154
                    enum object_info_flags flags,
155
                    struct strbuf *errmsg)
156
0
{
157
0
  struct odb_source_files *files = odb_source_files_downcast(source);
158
0
  enum odb_read_status ret_packed, ret_loose;
159
160
0
  ret_packed = odb_source_read_object_info(&files->packed->base, oid, oi,
161
0
             flags, errmsg);
162
0
  if (!ret_packed)
163
0
    return 0;
164
165
0
  ret_loose = odb_source_read_object_info(&files->loose->base, oid, oi, flags,
166
0
            ret_packed == ODB_READ_NOT_FOUND ? errmsg : NULL);
167
0
  if (!ret_loose)
168
0
    return 0;
169
170
  /*
171
   * Reading the packed object may have failed even though the object
172
   * exists, for example because it is corrupt. Report this failure to
173
   * the caller in case neither of the sources was able to read the
174
   * object, and prefer the error of the packed source in case both
175
   * reads have failed.
176
   */
177
0
  if (ret_packed != ODB_READ_NOT_FOUND)
178
0
    return ret_packed;
179
0
  return ret_loose;
180
0
}
181
182
static int odb_source_files_read_object_stream(struct odb_stream **out,
183
                 struct odb_source *source,
184
                 const struct object_id *oid)
185
0
{
186
0
  struct odb_source_files *files = odb_source_files_downcast(source);
187
0
  if (!odb_source_read_object_stream(out, &files->packed->base, oid) ||
188
0
      !odb_source_read_object_stream(out, &files->loose->base, oid))
189
0
    return 0;
190
0
  return -1;
191
0
}
192
193
static int odb_source_files_for_each_object(struct odb_source *source,
194
              const struct object_info *request,
195
              odb_for_each_object_cb cb,
196
              void *cb_data,
197
              const struct odb_for_each_object_options *opts)
198
0
{
199
0
  struct odb_source_files *files = odb_source_files_downcast(source);
200
0
  int ret;
201
202
0
  if (!(opts->flags & ODB_FOR_EACH_OBJECT_PROMISOR_ONLY)) {
203
0
    ret = odb_source_for_each_object(&files->loose->base, request, cb, cb_data, opts);
204
0
    if (ret)
205
0
      return ret;
206
0
  }
207
208
0
  ret = odb_source_for_each_object(&files->packed->base, request, cb, cb_data, opts);
209
0
  if (ret)
210
0
    return ret;
211
212
0
  return 0;
213
0
}
214
215
static int odb_source_files_count_objects(struct odb_source *source,
216
            enum odb_count_objects_flags flags,
217
            unsigned long *out)
218
0
{
219
0
  struct odb_source_files *files = odb_source_files_downcast(source);
220
0
  unsigned long count;
221
0
  int ret;
222
223
0
  ret = odb_source_count_objects(&files->packed->base, flags, &count);
224
0
  if (ret < 0)
225
0
    goto out;
226
227
0
  if (!(flags & ODB_COUNT_OBJECTS_APPROXIMATE)) {
228
0
    unsigned long loose_count;
229
230
0
    ret = odb_source_count_objects(&files->loose->base, flags, &loose_count);
231
0
    if (ret < 0)
232
0
      goto out;
233
234
0
    count += loose_count;
235
0
  }
236
237
0
  *out = count;
238
0
  ret = 0;
239
240
0
out:
241
0
  return ret;
242
0
}
243
244
static int odb_source_files_find_abbrev_len(struct odb_source *source,
245
              const struct object_id *oid,
246
              unsigned min_len,
247
              unsigned *out)
248
0
{
249
0
  struct odb_source_files *files = odb_source_files_downcast(source);
250
0
  unsigned len = min_len;
251
0
  int ret;
252
253
0
  ret = odb_source_find_abbrev_len(&files->packed->base, oid, len, &len);
254
0
  if (ret < 0)
255
0
    goto out;
256
257
0
  ret = odb_source_find_abbrev_len(&files->loose->base, oid, len, &len);
258
0
  if (ret < 0)
259
0
    goto out;
260
261
0
  *out = len;
262
0
  ret = 0;
263
264
0
out:
265
0
  return ret;
266
0
}
267
268
static int odb_source_files_freshen_object(struct odb_source *source,
269
             const struct object_id *oid,
270
             const time_t *mtime)
271
0
{
272
0
  struct odb_source_files *files = odb_source_files_downcast(source);
273
0
  if (odb_source_freshen_object(&files->packed->base, oid, mtime) ||
274
0
      odb_source_freshen_object(&files->loose->base, oid, mtime))
275
0
    return 1;
276
0
  return 0;
277
0
}
278
279
static int odb_source_files_write_object(struct odb_source *source,
280
           const void *buf, size_t len,
281
           enum object_type type,
282
           const struct object_id *oid,
283
           const struct object_id *compat_oid,
284
           const time_t *mtime,
285
           enum odb_write_object_flags flags)
286
0
{
287
0
  struct odb_source_files *files = odb_source_files_downcast(source);
288
0
  return odb_source_write_object(&files->loose->base, buf, len, type,
289
0
               oid, compat_oid, mtime, flags);
290
0
}
291
292
static int odb_source_files_write_object_stream(struct odb_source *source,
293
            struct odb_stream *stream,
294
            struct object_id *oid)
295
0
{
296
0
  struct odb_source_files *files = odb_source_files_downcast(source);
297
0
  return odb_source_write_object_stream(&files->loose->base, stream, oid);
298
0
}
299
300
static int odb_source_files_begin_transaction(struct odb_source *source,
301
                struct odb_transaction **out,
302
                enum odb_transaction_flags flags)
303
0
{
304
0
  return odb_transaction_files_begin(source, out, flags);
305
0
}
306
307
static int odb_source_files_read_alternates(struct odb_source *source,
308
              struct strvec *out)
309
0
{
310
0
  struct strbuf buf = STRBUF_INIT;
311
0
  char *path;
312
313
0
  path = xstrfmt("%s/info/alternates", source->path);
314
0
  if (strbuf_read_file(&buf, path, 1024) < 0) {
315
0
    warn_on_fopen_errors(path);
316
0
    free(path);
317
0
    return 0;
318
0
  }
319
0
  parse_alternates(buf.buf, '\n', source->path, out);
320
321
0
  strbuf_release(&buf);
322
0
  free(path);
323
0
  return 0;
324
0
}
325
326
static int too_many_loose_objects(struct odb_source_files *files, int limit)
327
0
{
328
0
  unsigned long loose_count;
329
330
0
  if (limit <= 0)
331
0
    return 0;
332
333
0
  if (odb_source_count_objects(&files->loose->base, ODB_COUNT_OBJECTS_APPROXIMATE,
334
0
             &loose_count) < 0)
335
0
    return 0;
336
337
  /*
338
   * This is weird, but stems from legacy behaviour: the GC auto
339
   * threshold was always essentially interpreted as if it was rounded up
340
   * to the next multiple 256 of, so we retain this behaviour for now.
341
   */
342
0
  return loose_count > (DIV_ROUND_UP(((unsigned long) limit), 256) * 256);
343
0
}
344
345
static struct packed_git *find_base_packs(struct odb_source_files *files,
346
            struct string_list *packs,
347
            unsigned long limit)
348
0
{
349
0
  struct packfile_list_entry *e;
350
0
  struct packed_git *base = NULL;
351
352
0
  for (e = packfile_store_get_packs(files->packed); e; e = e->next) {
353
0
    if (e->pack->is_cruft)
354
0
      continue;
355
0
    if (limit) {
356
0
      if ((uintmax_t) e->pack->pack_size >= limit)
357
0
        string_list_append(packs, e->pack->pack_name);
358
0
    } else if (!base || base->pack_size < e->pack->pack_size) {
359
0
      base = e->pack;
360
0
    }
361
0
  }
362
363
0
  if (base)
364
0
    string_list_append(packs, base->pack_name);
365
366
0
  return base;
367
0
}
368
369
static int too_many_packs(struct odb_source_files *files, int gc_auto_pack_limit)
370
0
{
371
0
  struct packfile_list_entry *e;
372
0
  int cnt = 0;
373
374
0
  if (gc_auto_pack_limit <= 0)
375
0
    return 0;
376
377
0
  for (e = packfile_store_get_packs(files->packed); e; e = e->next) {
378
0
    if (e->pack->pack_keep)
379
0
      continue;
380
    /*
381
     * Perhaps check the size of the pack and count only
382
     * very small ones here?
383
     */
384
0
    cnt++;
385
0
  }
386
0
  return gc_auto_pack_limit < cnt;
387
0
}
388
389
static uint64_t total_ram(void)
390
0
{
391
0
#if defined(HAVE_SYSINFO)
392
0
  struct sysinfo si;
393
394
0
  if (!sysinfo(&si)) {
395
0
    uint64_t total = si.totalram;
396
397
0
    if (si.mem_unit > 1)
398
0
      total *= (uint64_t)si.mem_unit;
399
0
    return total;
400
0
  }
401
#elif defined(HAVE_BSD_SYSCTL) && (defined(HW_MEMSIZE) || defined(HW_PHYSMEM) || defined(HW_PHYSMEM64))
402
  uint64_t physical_memory;
403
  int mib[2];
404
  size_t length;
405
406
  mib[0] = CTL_HW;
407
# if defined(HW_MEMSIZE)
408
  mib[1] = HW_MEMSIZE;
409
# elif defined(HW_PHYSMEM64)
410
  mib[1] = HW_PHYSMEM64;
411
# else
412
  mib[1] = HW_PHYSMEM;
413
# endif
414
  length = sizeof(physical_memory);
415
  if (!sysctl(mib, 2, &physical_memory, &length, NULL, 0)) {
416
    if (length == 4) {
417
      uint32_t mem;
418
419
      if (!sysctl(mib, 2, &mem, &length, NULL, 0))
420
        physical_memory = mem;
421
    }
422
    return physical_memory;
423
  }
424
#elif defined(GIT_WINDOWS_NATIVE)
425
  MEMORYSTATUSEX memInfo;
426
427
  memInfo.dwLength = sizeof(MEMORYSTATUSEX);
428
  if (GlobalMemoryStatusEx(&memInfo))
429
    return memInfo.ullTotalPhys;
430
#endif
431
0
  return 0;
432
0
}
433
434
static uint64_t estimate_repack_memory(struct odb_source_files *files,
435
               struct packed_git *pack)
436
0
{
437
0
  unsigned long max_delta_cache_size = DEFAULT_DELTA_CACHE_SIZE;
438
0
  unsigned long delta_base_cache_limit = DEFAULT_DELTA_BASE_CACHE_LIMIT;
439
0
  unsigned long nr_objects;
440
0
  size_t os_cache, heap;
441
442
0
  if (odb_source_count_objects(&files->base, ODB_COUNT_OBJECTS_APPROXIMATE,
443
0
             &nr_objects) < 0)
444
0
    return 0;
445
446
0
  if (!pack || !nr_objects)
447
0
    return 0;
448
449
0
  repo_config_get_ulong(files->base.odb->repo, "pack.deltacachesize",
450
0
            &max_delta_cache_size);
451
0
  repo_config_get_ulong(files->base.odb->repo, "core.deltabasecachelimit",
452
0
            &delta_base_cache_limit);
453
454
  /*
455
   * First we have to scan through at least one pack.
456
   * Assume enough room in OS file cache to keep the entire pack
457
   * or we may accidentally evict data of other processes from
458
   * the cache.
459
   */
460
0
  os_cache = pack->pack_size + pack->index_size;
461
  /* then pack-objects needs lots more for book keeping */
462
0
  heap = sizeof(struct object_entry) * nr_objects;
463
  /*
464
   * internal rev-list --all --objects takes up some memory too,
465
   * let's say half of it is for blobs
466
   */
467
0
  heap += sizeof(struct blob) * nr_objects / 2;
468
  /*
469
   * and the other half is for trees (commits and tags are
470
   * usually insignificant)
471
   */
472
0
  heap += sizeof(struct tree) * nr_objects / 2;
473
  /* and then obj_hash[], underestimated in fact */
474
0
  heap += sizeof(struct object *) * nr_objects;
475
  /* revindex is used also */
476
0
  heap += (sizeof(off_t) + sizeof(uint32_t)) * nr_objects;
477
  /*
478
   * read_sha1_file() (either at delta calculation phase, or
479
   * writing phase) also fills up the delta base cache
480
   */
481
0
  heap += delta_base_cache_limit;
482
  /* and of course pack-objects has its own delta cache */
483
0
  heap += max_delta_cache_size;
484
485
0
  return os_cache + heap;
486
0
}
487
488
static int keep_one_pack(struct string_list_item *item, void *data)
489
0
{
490
0
  struct strvec *args = data;
491
0
  strvec_pushf(args, "--keep-pack=%s", basename(item->string));
492
0
  return 0;
493
0
}
494
495
static void add_repack_all_option(struct repository *repo,
496
          const struct odb_optimize_options *opts,
497
          struct string_list *keep_pack,
498
          struct strvec *args)
499
0
{
500
0
  char *repack_filter = NULL;
501
0
  char *repack_filter_to = NULL;
502
503
0
  repo_config_get_string(repo, "gc.repackfilter", &repack_filter);
504
0
  repo_config_get_string(repo, "gc.repackfilterto", &repack_filter_to);
505
506
0
  if (opts->prune_expire && !strcmp(opts->prune_expire, "now") &&
507
0
      !(opts->cruft_packs && opts->expire_to))
508
0
    strvec_push(args, "-a");
509
0
  else if (opts->cruft_packs) {
510
0
    strvec_push(args, "--cruft");
511
0
    if (opts->prune_expire)
512
0
      strvec_pushf(args, "--cruft-expiration=%s", opts->prune_expire);
513
0
    if (opts->max_cruft_size)
514
0
      strvec_pushf(args, "--max-cruft-size=%lu",
515
0
             opts->max_cruft_size);
516
0
    if (opts->expire_to)
517
0
      strvec_pushf(args, "--expire-to=%s", opts->expire_to);
518
0
  } else {
519
0
    strvec_push(args, "-A");
520
0
    if (opts->prune_expire)
521
0
      strvec_pushf(args, "--unpack-unreachable=%s", opts->prune_expire);
522
0
  }
523
524
0
  if (keep_pack)
525
0
    for_each_string_list(keep_pack, keep_one_pack, args);
526
527
0
  if (repack_filter && *repack_filter)
528
0
    strvec_pushf(args, "--filter=%s", repack_filter);
529
0
  if (repack_filter_to && *repack_filter_to)
530
0
    strvec_pushf(args, "--filter-to=%s", repack_filter_to);
531
532
0
  free(repack_filter);
533
0
  free(repack_filter_to);
534
0
}
535
536
static void add_repack_incremental_option(struct strvec *args)
537
0
{
538
0
  strvec_push(args, "--no-write-bitmap-index");
539
0
}
540
541
bool odb_source_files_optimize_required(struct odb_source *source,
542
          const struct odb_optimize_options *opts)
543
0
{
544
0
  struct odb_source_files *files = odb_source_files_downcast(source);
545
0
  struct repository *repo = source->odb->repo;
546
547
0
  switch (opts->strategy) {
548
0
  case ODB_OPTIMIZE_INCREMENTAL: {
549
0
    int gc_auto_threshold = 6700;
550
0
    int gc_auto_pack_limit = 50;
551
552
0
    repo_config_get_int(repo, "gc.auto", &gc_auto_threshold);
553
0
    repo_config_get_int(repo, "gc.autopacklimit", &gc_auto_pack_limit);
554
555
    /*
556
     * Setting gc.auto to 0 or negative can disable the
557
     * automatic gc.
558
     */
559
0
    if (gc_auto_threshold <= 0)
560
0
      return false;
561
0
    if (!too_many_packs(files, gc_auto_pack_limit) &&
562
0
        !too_many_loose_objects(files, gc_auto_threshold))
563
0
      return false;
564
565
0
    return true;
566
0
  }
567
0
  case ODB_OPTIMIZE_GEOMETRIC: {
568
0
    struct pack_geometry geometry = {
569
0
      .split_factor = 2,
570
0
    };
571
0
    struct pack_objects_args po_args = {
572
0
      .local = 1,
573
0
    };
574
0
    struct existing_packs existing_packs = EXISTING_PACKS_INIT;
575
0
    struct string_list kept_packs = STRING_LIST_INIT_DUP;
576
0
    int auto_value = 6700;
577
0
    bool ret;
578
579
0
    repo_config_get_int(repo, "maintenance.geometric-repack.auto",
580
0
            &auto_value);
581
0
    if (!auto_value)
582
0
      return false;
583
0
    if (auto_value < 0)
584
0
      return true;
585
586
0
    repo_config_get_int(repo, "maintenance.geometric-repack.splitFactor",
587
0
            &geometry.split_factor);
588
589
0
    existing_packs.repo = repo;
590
0
    existing_packs_collect(&existing_packs, &kept_packs);
591
0
    pack_geometry_init(&geometry, &existing_packs, &po_args);
592
0
    pack_geometry_split(&geometry);
593
594
    /*
595
     * When we'd merge at least two packs with one another we always
596
     * perform the repack.
597
     */
598
0
    if (geometry.split) {
599
0
      ret = true;
600
0
      goto out;
601
0
    }
602
603
    /*
604
     * Otherwise, we estimate the number of loose objects to determine
605
     * whether we want to create a new packfile or not.
606
     */
607
0
    if (too_many_loose_objects(files, auto_value)) {
608
0
      ret = true;
609
0
      goto out;
610
0
    }
611
612
0
    ret = false;
613
614
0
  out:
615
0
    existing_packs_release(&existing_packs);
616
0
    pack_geometry_release(&geometry);
617
0
    return ret;
618
0
  }
619
0
  default:
620
0
    BUG("unknown maintenance strategy '%d'", opts->strategy);
621
0
  }
622
0
}
623
624
int odb_source_files_optimize(struct odb_source *source,
625
            const struct odb_optimize_options *opts)
626
0
{
627
0
  struct odb_source_files *files = odb_source_files_downcast(source);
628
0
  struct repository *repo = source->odb->repo;
629
0
  struct child_process repack_cmd = CHILD_PROCESS_INIT;
630
0
  unsigned long big_pack_threshold = 0;
631
0
  int gc_auto_threshold = 6700;
632
0
  int gc_auto_pack_limit = 50;
633
0
  int ret;
634
635
0
  repo_config_get_int(repo, "gc.auto", &gc_auto_threshold);
636
0
  repo_config_get_int(repo, "gc.autopacklimit", &gc_auto_pack_limit);
637
0
  repo_config_get_ulong(repo, "gc.bigpackthreshold", &big_pack_threshold);
638
639
0
  if (repo->repository_format_precious_objects)
640
0
    return 0;
641
642
0
  repack_cmd.git_cmd = 1;
643
0
  repack_cmd.odb_to_close = repo->objects;
644
645
0
  strvec_pushl(&repack_cmd.args, "repack", "-d", "-l", NULL);
646
0
  if (opts->flags & ODB_OPTIMIZE_NO_REUSE_DELTAS)
647
0
    strvec_push(&repack_cmd.args, "-f");
648
0
  if (opts->depth > 0)
649
0
    strvec_pushf(&repack_cmd.args, "--depth=%d", opts->depth);
650
0
  if (opts->window > 0)
651
0
    strvec_pushf(&repack_cmd.args, "--window=%d", opts->window);
652
0
  if (!(opts->flags & ODB_OPTIMIZE_VERBOSE))
653
0
    strvec_push(&repack_cmd.args, "-q");
654
655
  /*
656
   * There's three cases we need to consider:
657
   *
658
   *   - If we're invoked without `--auto` we'll need to perform a full
659
   *     repack.
660
   *
661
   *   - If we're invoked with `--auto` and there's too many packs, then
662
   *     we perform a full repack, as well.
663
   *
664
   *   - Otherwise we perform an incremental repack.
665
   */
666
0
  switch (opts->strategy) {
667
0
  case ODB_OPTIMIZE_INCREMENTAL:
668
0
    if (!(opts->flags & ODB_OPTIMIZE_AUTO)) {
669
0
      struct string_list keep_pack = STRING_LIST_INIT_NODUP;
670
671
0
      if (opts->keep_largest_pack != -1) {
672
0
        if (opts->keep_largest_pack)
673
0
          find_base_packs(files, &keep_pack, 0);
674
0
      } else if (big_pack_threshold) {
675
0
        find_base_packs(files, &keep_pack, big_pack_threshold);
676
0
      }
677
678
0
      add_repack_all_option(repo, opts, &keep_pack, &repack_cmd.args);
679
0
      string_list_clear(&keep_pack, 0);
680
0
    } else {
681
0
      if (too_many_packs(files, gc_auto_pack_limit)) {
682
0
        struct string_list keep_pack = STRING_LIST_INIT_NODUP;
683
684
0
        if (big_pack_threshold) {
685
0
          find_base_packs(files, &keep_pack, big_pack_threshold);
686
0
          if (keep_pack.nr >= (unsigned long) gc_auto_pack_limit) {
687
0
            string_list_clear(&keep_pack, 0);
688
0
            find_base_packs(files, &keep_pack, 0);
689
0
          }
690
0
        } else {
691
0
          struct packed_git *p = find_base_packs(files, &keep_pack, 0);
692
0
          uint64_t mem_have, mem_want;
693
694
0
          mem_have = total_ram();
695
0
          mem_want = estimate_repack_memory(files, p);
696
697
          /*
698
           * Only allow 1/2 of memory for pack-objects, leave
699
           * the rest for the OS and other processes in the
700
           * system.
701
           */
702
0
          if (!mem_have || mem_want < mem_have / 2)
703
0
            string_list_clear(&keep_pack, 0);
704
0
        }
705
706
0
        add_repack_all_option(repo, opts, &keep_pack, &repack_cmd.args);
707
0
        string_list_clear(&keep_pack, 0);
708
0
      } else {
709
0
        add_repack_incremental_option(&repack_cmd.args);
710
0
      }
711
0
    }
712
713
0
    break;
714
0
  case ODB_OPTIMIZE_GEOMETRIC: {
715
0
    struct pack_geometry geometry = {
716
0
      .split_factor = 2,
717
0
    };
718
0
    struct pack_objects_args po_args = {
719
0
      .local = 1,
720
0
    };
721
0
    struct existing_packs existing_packs = EXISTING_PACKS_INIT;
722
0
    struct string_list kept_packs = STRING_LIST_INIT_DUP;
723
724
0
    repo_config_get_int(repo, "maintenance.geometric-repack.splitFactor",
725
0
            &geometry.split_factor);
726
727
0
    existing_packs.repo = repo;
728
0
    existing_packs_collect(&existing_packs, &kept_packs);
729
0
    pack_geometry_init(&geometry, &existing_packs, &po_args);
730
0
    pack_geometry_split(&geometry);
731
732
0
    if (geometry.split < geometry.pack_nr) {
733
0
      strvec_pushf(&repack_cmd.args, "--geometric=%d",
734
0
             geometry.split_factor);
735
0
    } else {
736
0
      add_repack_all_option(repo, opts, NULL, &repack_cmd.args);
737
0
    }
738
0
    if (repo->settings.core_multi_pack_index)
739
0
      strvec_push(&repack_cmd.args, "--write-midx");
740
741
0
    existing_packs_release(&existing_packs);
742
0
    pack_geometry_release(&geometry);
743
0
    break;
744
0
  }
745
0
  default:
746
0
    die("unknown maintenance strategy '%d'", opts->strategy);
747
0
  }
748
749
0
  if (run_command(&repack_cmd)) {
750
0
    ret = error("failed to run %s", repack_cmd.args.v[0]);
751
0
    goto out;
752
0
  }
753
754
  /* Geometric repacking uses cruft packs, so we don't have to prune separately. */
755
0
  if (opts->strategy != ODB_OPTIMIZE_GEOMETRIC && opts->prune_expire) {
756
0
    struct child_process prune_cmd = CHILD_PROCESS_INIT;
757
758
0
    strvec_pushl(&prune_cmd.args, "prune", "--expire", NULL);
759
    /* run `git prune` even if using cruft packs */
760
0
    strvec_push(&prune_cmd.args, opts->prune_expire);
761
0
    if (!(opts->flags & ODB_OPTIMIZE_VERBOSE))
762
0
      strvec_push(&prune_cmd.args, "--no-progress");
763
0
    if (repo_has_promisor_remote(repo))
764
0
      strvec_push(&prune_cmd.args,
765
0
            "--exclude-promisor-objects");
766
0
    prune_cmd.git_cmd = 1;
767
768
0
    if (run_command(&prune_cmd)) {
769
0
      ret = error("failed to run %s", prune_cmd.args.v[0]);
770
0
      goto out;
771
0
    }
772
0
  }
773
774
0
  if (opts->flags & ODB_OPTIMIZE_AUTO && too_many_loose_objects(files, gc_auto_threshold))
775
0
    warning(_("There are too many unreachable loose objects; "
776
0
      "run 'git prune' to remove them."));
777
778
0
  ret = 0;
779
780
0
out:
781
0
  return ret;
782
0
}
783
784
struct odb_pack_generator_files {
785
  struct odb_pack_generator base;
786
  struct child_process cp;
787
};
788
789
static int odb_pack_generator_files_finish(struct odb_pack_generator *_generator)
790
0
{
791
0
  struct odb_pack_generator_files *generator =
792
0
    (struct odb_pack_generator_files *)_generator;
793
0
  int ret;
794
795
0
  ret = finish_command(&generator->cp);
796
0
  free(generator);
797
798
0
  if (ret) {
799
    /*
800
     * On failure, pack-objects is expected to have written a
801
     * useful error message to its standard error stream already.
802
     * Death by signal is worth mentioning, though, with the
803
     * exception of SIGPIPE: that is a normal occurrence when the
804
     * consumer of the pack hangs up.
805
     */
806
0
    if (ret > 128 && ret - 128 == SIGPIPE)
807
0
      return -1;
808
0
    if (ret > 128)
809
0
      error(_("pack-objects died of signal %d"), ret - 128);
810
0
    return -1;
811
0
  }
812
813
0
  return 0;
814
0
}
815
816
static int odb_source_files_generate_pack(struct odb_source *source UNUSED,
817
            struct odb_pack_generator **out,
818
            const struct odb_generate_pack_options *opts)
819
0
{
820
0
  struct odb_pack_generator_files *generator;
821
0
  struct child_process *cp;
822
0
  FILE *in;
823
824
0
  CALLOC_ARRAY(generator, 1);
825
0
  child_process_init(&generator->cp);
826
0
  cp = &generator->cp;
827
828
  /*
829
   * The hook is expected to spawn "$hook git pack-objects <args...>"
830
   * and to behave like git-pack-objects(1) would have. This can for
831
   * example be used to serve precomputed packfiles.
832
   */
833
0
  if (opts->pack_objects_hook) {
834
0
    strvec_push(&cp->args, opts->pack_objects_hook);
835
0
    strvec_push(&cp->args, "git");
836
0
    cp->use_shell = 1;
837
0
  } else {
838
0
    cp->git_cmd = 1;
839
0
  }
840
841
  /*
842
   * The caller-provided shallow boundary overrides any shallow state
843
   * that the repository itself may have, so the shallow file needs to
844
   * be neutralized.
845
   */
846
0
  if (opts->shallows.nr) {
847
0
    strvec_push(&cp->args, "--shallow-file");
848
0
    strvec_push(&cp->args, "");
849
0
  }
850
0
  strvec_push(&cp->args, "pack-objects");
851
0
  strvec_push(&cp->args, "--revs");
852
0
  strvec_push(&cp->args, "--stdout");
853
0
  if (opts->thin)
854
0
    strvec_push(&cp->args, "--thin");
855
0
  if (opts->shallow)
856
0
    strvec_push(&cp->args, "--shallow");
857
0
  if (opts->ofs_delta)
858
0
    strvec_push(&cp->args, "--delta-base-offset");
859
0
  if (opts->include_tag)
860
0
    strvec_push(&cp->args, "--include-tag");
861
0
  if (opts->missing_allow_promisor)
862
0
    strvec_push(&cp->args, "--missing=allow-promisor");
863
0
  if (opts->disable_bitmaps)
864
0
    strvec_push(&cp->args, "--no-use-bitmap-index");
865
0
  switch (opts->progress) {
866
0
  case ODB_GENERATE_PACK_PROGRESS_NONE:
867
0
    strvec_push(&cp->args, "--quiet");
868
0
    break;
869
0
  case ODB_GENERATE_PACK_PROGRESS_STANDARD:
870
0
    strvec_push(&cp->args, "--progress");
871
0
    break;
872
0
  case ODB_GENERATE_PACK_PROGRESS_VERBOSE:
873
0
    strvec_push(&cp->args, "--all-progress");
874
0
    break;
875
0
  default:
876
0
    BUG("unknown progress option %d", opts->progress);
877
0
  }
878
0
  if (opts->filter_spec)
879
0
    strvec_pushf(&cp->args, "--filter=%s", opts->filter_spec);
880
0
  if (opts->uri_protocols)
881
0
    for (size_t i = 0; i < opts->uri_protocols->nr; i++)
882
0
      strvec_pushf(&cp->args, "--uri-protocol=%s",
883
0
             opts->uri_protocols->items[i].string);
884
885
0
  cp->in = -1;
886
0
  cp->out = opts->pack_fd;
887
0
  cp->err = opts->progress_fd;
888
0
  cp->clean_on_exit = 1;
889
890
0
  if (start_command(cp)) {
891
0
    free(generator);
892
0
    return error(_("could not spawn pack-objects"));
893
0
  }
894
895
  /*
896
   * Feed the objects to pack-objects. This is safe to do synchronously
897
   * because pack-objects consumes all of its standard input before it
898
   * starts to generate the pack.
899
   */
900
0
  in = xfdopen(cp->in, "w");
901
0
  for (size_t i = 0; i < opts->shallows.nr; i++)
902
0
    fprintf(in, "--shallow %s\n", oid_to_hex(&opts->shallows.oid[i]));
903
0
  for (size_t i = 0; i < opts->wants.nr; i++)
904
0
    fprintf(in, "%s\n", oid_to_hex(&opts->wants.oid[i]));
905
0
  fprintf(in, "--not\n");
906
0
  for (size_t i = 0; i < opts->haves.nr; i++)
907
0
    fprintf(in, "%s\n", oid_to_hex(&opts->haves.oid[i]));
908
0
  fprintf(in, "\n");
909
0
  fflush(in);
910
0
  if (ferror(in)) {
911
0
    error(_("error writing to pack-objects"));
912
0
    fclose(in);
913
0
    if (opts->pack_fd < 0)
914
0
      close(cp->out);
915
0
    if (opts->progress_fd < 0)
916
0
      close(cp->err);
917
0
    finish_command(cp);
918
0
    free(generator);
919
0
    return -1;
920
0
  }
921
0
  fclose(in);
922
923
0
  generator->base.out = opts->pack_fd < 0 ? cp->out : -1;
924
0
  generator->base.err = opts->progress_fd < 0 ? cp->err : -1;
925
0
  generator->base.finish = odb_pack_generator_files_finish;
926
927
0
  *out = &generator->base;
928
0
  return 0;
929
0
}
930
931
static int odb_source_files_fsck(struct odb_source *source,
932
         struct odb_fsck_options *opts)
933
0
{
934
0
  struct odb_source_files *files = odb_source_files_downcast(source);
935
0
  int ret = 0;
936
937
0
  if (!(opts->flags & ODB_FSCK_FULL) && !source->local)
938
0
    return 0;
939
940
0
  ret |= odb_source_fsck(&files->loose->base, opts);
941
0
  ret |= odb_source_fsck(&files->packed->base, opts);
942
943
0
  return ret;
944
0
}
945
946
struct odb_source_files *odb_source_files_new(struct object_database *odb,
947
                const char *path,
948
                bool local)
949
0
{
950
0
  struct odb_source_files *files;
951
952
0
  CALLOC_ARRAY(files, 1);
953
0
  odb_source_init(&files->base, odb, ODB_SOURCE_FILES, path, local);
954
0
  files->loose = odb_source_loose_new(odb, path, local);
955
0
  files->packed = odb_source_packed_new(odb, path, local);
956
957
0
  files->base.free = odb_source_files_free;
958
0
  files->base.close = odb_source_files_close;
959
0
  files->base.create_on_disk = odb_source_files_create_on_disk;
960
0
  files->base.prepare = odb_source_files_prepare;
961
0
  files->base.fsck = odb_source_files_fsck;
962
0
  files->base.read_object_info = odb_source_files_read_object_info;
963
0
  files->base.read_object_stream = odb_source_files_read_object_stream;
964
0
  files->base.for_each_object = odb_source_files_for_each_object;
965
0
  files->base.count_objects = odb_source_files_count_objects;
966
0
  files->base.find_abbrev_len = odb_source_files_find_abbrev_len;
967
0
  files->base.freshen_object = odb_source_files_freshen_object;
968
0
  files->base.write_object = odb_source_files_write_object;
969
0
  files->base.write_object_stream = odb_source_files_write_object_stream;
970
0
  files->base.begin_transaction = odb_source_files_begin_transaction;
971
0
  files->base.read_alternates = odb_source_files_read_alternates;
972
0
  files->base.optimize = odb_source_files_optimize;
973
0
  files->base.optimize_required = odb_source_files_optimize_required;
974
0
  files->base.generate_pack = odb_source_files_generate_pack;
975
976
  /*
977
   * Ideally, we would only ever store absolute paths in the source. This
978
   * is not (yet) possible though because we access and assume relative
979
   * paths in the primary ODB source in some user-facing functionality.
980
   */
981
0
  if (!is_absolute_path(path))
982
0
    chdir_notify_register(odb_source_files_reparent, files);
983
984
0
  return files;
985
0
}