Coverage Report

Created: 2026-01-09 07:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/git/pack-write.c
Line
Count
Source
1
#include "git-compat-util.h"
2
#include "environment.h"
3
#include "gettext.h"
4
#include "hex.h"
5
#include "pack.h"
6
#include "csum-file.h"
7
#include "remote.h"
8
#include "chunk-format.h"
9
#include "object-file.h"
10
#include "pack-mtimes.h"
11
#include "pack-objects.h"
12
#include "pack-revindex.h"
13
#include "path.h"
14
#include "repository.h"
15
#include "strbuf.h"
16
17
void reset_pack_idx_option(struct pack_idx_option *opts)
18
0
{
19
0
  memset(opts, 0, sizeof(*opts));
20
0
  opts->version = 2;
21
0
  opts->off32_limit = 0x7fffffff;
22
0
  opts->delta_base_cache_limit = DEFAULT_DELTA_BASE_CACHE_LIMIT;
23
0
}
24
25
static int sha1_compare(const void *_a, const void *_b)
26
0
{
27
0
  struct pack_idx_entry *a = *(struct pack_idx_entry **)_a;
28
0
  struct pack_idx_entry *b = *(struct pack_idx_entry **)_b;
29
0
  return oidcmp(&a->oid, &b->oid);
30
0
}
31
32
static int cmp_uint32(const void *a_, const void *b_)
33
0
{
34
0
  uint32_t a = *((uint32_t *)a_);
35
0
  uint32_t b = *((uint32_t *)b_);
36
37
0
  return (a < b) ? -1 : (a != b);
38
0
}
39
40
static int need_large_offset(off_t offset, const struct pack_idx_option *opts)
41
0
{
42
0
  uint32_t ofsval;
43
44
0
  if ((offset >> 31) || (opts->off32_limit < offset))
45
0
    return 1;
46
0
  if (!opts->anomaly_nr)
47
0
    return 0;
48
0
  ofsval = offset;
49
0
  return !!bsearch(&ofsval, opts->anomaly, opts->anomaly_nr,
50
0
       sizeof(ofsval), cmp_uint32);
51
0
}
52
53
/*
54
 * The *sha1 contains the pack content SHA1 hash.
55
 * The objects array passed in will be sorted by SHA1 on exit.
56
 */
57
const char *write_idx_file(struct repository *repo,
58
         const char *index_name, struct pack_idx_entry **objects,
59
         int nr_objects, const struct pack_idx_option *opts,
60
         const unsigned char *sha1)
61
0
{
62
0
  struct hashfile *f;
63
0
  struct pack_idx_entry **sorted_by_sha, **list, **last;
64
0
  off_t last_obj_offset = 0;
65
0
  int i, fd;
66
0
  uint32_t index_version;
67
68
0
  if (nr_objects) {
69
0
    sorted_by_sha = objects;
70
0
    list = sorted_by_sha;
71
0
    last = sorted_by_sha + nr_objects;
72
0
    for (i = 0; i < nr_objects; ++i) {
73
0
      if (objects[i]->offset > last_obj_offset)
74
0
        last_obj_offset = objects[i]->offset;
75
0
    }
76
0
    QSORT(sorted_by_sha, nr_objects, sha1_compare);
77
0
  }
78
0
  else
79
0
    sorted_by_sha = list = last = NULL;
80
81
0
  if (opts->flags & WRITE_IDX_VERIFY) {
82
0
    assert(index_name);
83
0
    f = hashfd_check(repo->hash_algo, index_name);
84
0
  } else {
85
0
    if (!index_name) {
86
0
      struct strbuf tmp_file = STRBUF_INIT;
87
0
      fd = odb_mkstemp(repo->objects, &tmp_file,
88
0
           "pack/tmp_idx_XXXXXX");
89
0
      index_name = strbuf_detach(&tmp_file, NULL);
90
0
    } else {
91
0
      unlink(index_name);
92
0
      fd = xopen(index_name, O_CREAT|O_EXCL|O_WRONLY, 0600);
93
0
    }
94
0
    f = hashfd(repo->hash_algo, fd, index_name);
95
0
  }
96
97
  /* if last object's offset is >= 2^31 we should use index V2 */
98
0
  index_version = need_large_offset(last_obj_offset, opts) ? 2 : opts->version;
99
100
  /* index versions 2 and above need a header */
101
0
  if (index_version >= 2) {
102
0
    struct pack_idx_header hdr;
103
0
    hdr.idx_signature = htonl(PACK_IDX_SIGNATURE);
104
0
    hdr.idx_version = htonl(index_version);
105
0
    hashwrite(f, &hdr, sizeof(hdr));
106
0
  }
107
108
  /*
109
   * Write the first-level table (the list is sorted,
110
   * but we use a 256-entry lookup to be able to avoid
111
   * having to do eight extra binary search iterations).
112
   */
113
0
  for (i = 0; i < 256; i++) {
114
0
    struct pack_idx_entry **next = list;
115
0
    while (next < last) {
116
0
      struct pack_idx_entry *obj = *next;
117
0
      if (obj->oid.hash[0] != i)
118
0
        break;
119
0
      next++;
120
0
    }
121
0
    hashwrite_be32(f, next - sorted_by_sha);
122
0
    list = next;
123
0
  }
124
125
  /*
126
   * Write the actual SHA1 entries..
127
   */
128
0
  list = sorted_by_sha;
129
0
  for (i = 0; i < nr_objects; i++) {
130
0
    struct pack_idx_entry *obj = *list++;
131
0
    if (index_version < 2)
132
0
      hashwrite_be32(f, obj->offset);
133
0
    hashwrite(f, obj->oid.hash, repo->hash_algo->rawsz);
134
0
    if ((opts->flags & WRITE_IDX_STRICT) &&
135
0
        (i && oideq(&list[-2]->oid, &obj->oid)))
136
0
      die("The same object %s appears twice in the pack",
137
0
          oid_to_hex(&obj->oid));
138
0
  }
139
140
0
  if (index_version >= 2) {
141
0
    unsigned int nr_large_offset = 0;
142
143
    /* write the crc32 table */
144
0
    list = sorted_by_sha;
145
0
    for (i = 0; i < nr_objects; i++) {
146
0
      struct pack_idx_entry *obj = *list++;
147
0
      hashwrite_be32(f, obj->crc32);
148
0
    }
149
150
    /* write the 32-bit offset table */
151
0
    list = sorted_by_sha;
152
0
    for (i = 0; i < nr_objects; i++) {
153
0
      struct pack_idx_entry *obj = *list++;
154
0
      uint32_t offset;
155
156
0
      offset = (need_large_offset(obj->offset, opts)
157
0
          ? (0x80000000 | nr_large_offset++)
158
0
          : obj->offset);
159
0
      hashwrite_be32(f, offset);
160
0
    }
161
162
    /* write the large offset table */
163
0
    list = sorted_by_sha;
164
0
    while (nr_large_offset) {
165
0
      struct pack_idx_entry *obj = *list++;
166
0
      uint64_t offset = obj->offset;
167
168
0
      if (!need_large_offset(offset, opts))
169
0
        continue;
170
0
      hashwrite_be64(f, offset);
171
0
      nr_large_offset--;
172
0
    }
173
0
  }
174
175
0
  hashwrite(f, sha1, repo->hash_algo->rawsz);
176
0
  finalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA,
177
0
        CSUM_HASH_IN_STREAM | CSUM_CLOSE |
178
0
        ((opts->flags & WRITE_IDX_VERIFY) ? 0 : CSUM_FSYNC));
179
0
  return index_name;
180
0
}
181
182
static int pack_order_cmp(const void *va, const void *vb, void *ctx)
183
0
{
184
0
  struct pack_idx_entry **objects = ctx;
185
186
0
  off_t oa = objects[*(uint32_t*)va]->offset;
187
0
  off_t ob = objects[*(uint32_t*)vb]->offset;
188
189
0
  if (oa < ob)
190
0
    return -1;
191
0
  if (oa > ob)
192
0
    return 1;
193
0
  return 0;
194
0
}
195
196
static void write_rev_header(const struct git_hash_algo *hash_algo,
197
           struct hashfile *f)
198
0
{
199
0
  hashwrite_be32(f, RIDX_SIGNATURE);
200
0
  hashwrite_be32(f, RIDX_VERSION);
201
0
  hashwrite_be32(f, oid_version(hash_algo));
202
0
}
203
204
static void write_rev_index_positions(struct hashfile *f,
205
              uint32_t *pack_order,
206
              uint32_t nr_objects)
207
0
{
208
0
  uint32_t i;
209
0
  for (i = 0; i < nr_objects; i++)
210
0
    hashwrite_be32(f, pack_order[i]);
211
0
}
212
213
static void write_rev_trailer(const struct git_hash_algo *hash_algo,
214
            struct hashfile *f, const unsigned char *hash)
215
0
{
216
0
  hashwrite(f, hash, hash_algo->rawsz);
217
0
}
218
219
char *write_rev_file(struct repository *repo,
220
         const char *rev_name,
221
         struct pack_idx_entry **objects,
222
         uint32_t nr_objects,
223
         const unsigned char *hash,
224
         unsigned flags)
225
0
{
226
0
  uint32_t *pack_order;
227
0
  uint32_t i;
228
0
  char *ret;
229
230
0
  if (!(flags & WRITE_REV) && !(flags & WRITE_REV_VERIFY))
231
0
    return NULL;
232
233
0
  ALLOC_ARRAY(pack_order, nr_objects);
234
0
  for (i = 0; i < nr_objects; i++)
235
0
    pack_order[i] = i;
236
0
  QSORT_S(pack_order, nr_objects, pack_order_cmp, objects);
237
238
0
  ret = write_rev_file_order(repo, rev_name, pack_order, nr_objects,
239
0
           hash, flags);
240
241
0
  free(pack_order);
242
243
0
  return ret;
244
0
}
245
246
char *write_rev_file_order(struct repository *repo,
247
         const char *rev_name,
248
         uint32_t *pack_order,
249
         uint32_t nr_objects,
250
         const unsigned char *hash,
251
         unsigned flags)
252
0
{
253
0
  struct hashfile *f;
254
0
  char *path;
255
0
  int fd;
256
257
0
  if ((flags & WRITE_REV) && (flags & WRITE_REV_VERIFY))
258
0
    die(_("cannot both write and verify reverse index"));
259
260
0
  if (flags & WRITE_REV) {
261
0
    if (!rev_name) {
262
0
      struct strbuf tmp_file = STRBUF_INIT;
263
0
      fd = odb_mkstemp(repo->objects, &tmp_file,
264
0
           "pack/tmp_rev_XXXXXX");
265
0
      path = strbuf_detach(&tmp_file, NULL);
266
0
    } else {
267
0
      unlink(rev_name);
268
0
      fd = xopen(rev_name, O_CREAT|O_EXCL|O_WRONLY, 0600);
269
0
      path = xstrdup(rev_name);
270
0
    }
271
0
    f = hashfd(repo->hash_algo, fd, path);
272
0
  } else if (flags & WRITE_REV_VERIFY) {
273
0
    struct stat statbuf;
274
0
    if (stat(rev_name, &statbuf)) {
275
0
      if (errno == ENOENT) {
276
        /* .rev files are optional */
277
0
        return NULL;
278
0
      } else
279
0
        die_errno(_("could not stat: %s"), rev_name);
280
0
    }
281
0
    f = hashfd_check(repo->hash_algo, rev_name);
282
0
    path = xstrdup(rev_name);
283
0
  } else {
284
0
    return NULL;
285
0
  }
286
287
0
  write_rev_header(repo->hash_algo, f);
288
289
0
  write_rev_index_positions(f, pack_order, nr_objects);
290
0
  write_rev_trailer(repo->hash_algo, f, hash);
291
292
0
  if (adjust_shared_perm(repo, path) < 0)
293
0
    die(_("failed to make %s readable"), path);
294
295
0
  finalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA,
296
0
        CSUM_HASH_IN_STREAM | CSUM_CLOSE |
297
0
        ((flags & WRITE_IDX_VERIFY) ? 0 : CSUM_FSYNC));
298
299
0
  return path;
300
0
}
301
302
static void write_mtimes_header(const struct git_hash_algo *hash_algo,
303
        struct hashfile *f)
304
0
{
305
0
  hashwrite_be32(f, MTIMES_SIGNATURE);
306
0
  hashwrite_be32(f, MTIMES_VERSION);
307
0
  hashwrite_be32(f, oid_version(hash_algo));
308
0
}
309
310
/*
311
 * Writes the object mtimes of "objects" for use in a .mtimes file.
312
 * Note that objects must be in lexicographic (index) order, which is
313
 * the expected ordering of these values in the .mtimes file.
314
 */
315
static void write_mtimes_objects(struct hashfile *f,
316
         struct packing_data *to_pack,
317
         struct pack_idx_entry **objects,
318
         uint32_t nr_objects)
319
0
{
320
0
  uint32_t i;
321
0
  for (i = 0; i < nr_objects; i++) {
322
0
    struct object_entry *e = (struct object_entry*)objects[i];
323
0
    hashwrite_be32(f, oe_cruft_mtime(to_pack, e));
324
0
  }
325
0
}
326
327
static void write_mtimes_trailer(const struct git_hash_algo *hash_algo,
328
         struct hashfile *f, const unsigned char *hash)
329
0
{
330
0
  hashwrite(f, hash, hash_algo->rawsz);
331
0
}
332
333
static char *write_mtimes_file(struct repository *repo,
334
             struct packing_data *to_pack,
335
             struct pack_idx_entry **objects,
336
             uint32_t nr_objects,
337
             const unsigned char *hash)
338
0
{
339
0
  struct strbuf tmp_file = STRBUF_INIT;
340
0
  char *mtimes_name;
341
0
  struct hashfile *f;
342
0
  int fd;
343
344
0
  if (!to_pack)
345
0
    BUG("cannot call write_mtimes_file with NULL packing_data");
346
347
0
  fd = odb_mkstemp(repo->objects, &tmp_file, "pack/tmp_mtimes_XXXXXX");
348
0
  mtimes_name = strbuf_detach(&tmp_file, NULL);
349
0
  f = hashfd(repo->hash_algo, fd, mtimes_name);
350
351
0
  write_mtimes_header(repo->hash_algo, f);
352
0
  write_mtimes_objects(f, to_pack, objects, nr_objects);
353
0
  write_mtimes_trailer(repo->hash_algo, f, hash);
354
355
0
  if (adjust_shared_perm(repo, mtimes_name) < 0)
356
0
    die(_("failed to make %s readable"), mtimes_name);
357
358
0
  finalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA,
359
0
        CSUM_HASH_IN_STREAM | CSUM_CLOSE | CSUM_FSYNC);
360
361
0
  return mtimes_name;
362
0
}
363
364
off_t write_pack_header(struct hashfile *f, uint32_t nr_entries)
365
0
{
366
0
  struct pack_header hdr;
367
368
0
  hdr.hdr_signature = htonl(PACK_SIGNATURE);
369
0
  hdr.hdr_version = htonl(PACK_VERSION);
370
0
  hdr.hdr_entries = htonl(nr_entries);
371
0
  hashwrite(f, &hdr, sizeof(hdr));
372
0
  return sizeof(hdr);
373
0
}
374
375
/*
376
 * Update pack header with object_count and compute new SHA1 for pack data
377
 * associated to pack_fd, and write that SHA1 at the end.  That new SHA1
378
 * is also returned in new_pack_sha1.
379
 *
380
 * If partial_pack_sha1 is non null, then the SHA1 of the existing pack
381
 * (without the header update) is computed and validated against the
382
 * one provided in partial_pack_sha1.  The validation is performed at
383
 * partial_pack_offset bytes in the pack file.  The SHA1 of the remaining
384
 * data (i.e. from partial_pack_offset to the end) is then computed and
385
 * returned in partial_pack_sha1.
386
 *
387
 * Note that new_pack_sha1 is updated last, so both new_pack_sha1 and
388
 * partial_pack_sha1 can refer to the same buffer if the caller is not
389
 * interested in the resulting SHA1 of pack data above partial_pack_offset.
390
 */
391
void fixup_pack_header_footer(const struct git_hash_algo *hash_algo,
392
       int pack_fd,
393
       unsigned char *new_pack_hash,
394
       const char *pack_name,
395
       uint32_t object_count,
396
       unsigned char *partial_pack_hash,
397
       off_t partial_pack_offset)
398
0
{
399
0
  int aligned_sz, buf_sz = 8 * 1024;
400
0
  struct git_hash_ctx old_hash_ctx, new_hash_ctx;
401
0
  struct pack_header hdr;
402
0
  char *buf;
403
0
  ssize_t read_result;
404
405
0
  hash_algo->init_fn(&old_hash_ctx);
406
0
  hash_algo->init_fn(&new_hash_ctx);
407
408
0
  if (lseek(pack_fd, 0, SEEK_SET) != 0)
409
0
    die_errno("Failed seeking to start of '%s'", pack_name);
410
0
  read_result = read_in_full(pack_fd, &hdr, sizeof(hdr));
411
0
  if (read_result < 0)
412
0
    die_errno("Unable to reread header of '%s'", pack_name);
413
0
  else if (read_result != sizeof(hdr))
414
0
    die_errno("Unexpected short read for header of '%s'",
415
0
        pack_name);
416
0
  if (lseek(pack_fd, 0, SEEK_SET) != 0)
417
0
    die_errno("Failed seeking to start of '%s'", pack_name);
418
0
  git_hash_update(&old_hash_ctx, &hdr, sizeof(hdr));
419
0
  hdr.hdr_entries = htonl(object_count);
420
0
  git_hash_update(&new_hash_ctx, &hdr, sizeof(hdr));
421
0
  write_or_die(pack_fd, &hdr, sizeof(hdr));
422
0
  partial_pack_offset -= sizeof(hdr);
423
424
0
  buf = xmalloc(buf_sz);
425
0
  aligned_sz = buf_sz - sizeof(hdr);
426
0
  for (;;) {
427
0
    ssize_t m, n;
428
0
    m = (partial_pack_hash && partial_pack_offset < aligned_sz) ?
429
0
      partial_pack_offset : aligned_sz;
430
0
    n = xread(pack_fd, buf, m);
431
0
    if (!n)
432
0
      break;
433
0
    if (n < 0)
434
0
      die_errno("Failed to checksum '%s'", pack_name);
435
0
    git_hash_update(&new_hash_ctx, buf, n);
436
437
0
    aligned_sz -= n;
438
0
    if (!aligned_sz)
439
0
      aligned_sz = buf_sz;
440
441
0
    if (!partial_pack_hash)
442
0
      continue;
443
444
0
    git_hash_update(&old_hash_ctx, buf, n);
445
0
    partial_pack_offset -= n;
446
0
    if (partial_pack_offset == 0) {
447
0
      unsigned char hash[GIT_MAX_RAWSZ];
448
0
      git_hash_final(hash, &old_hash_ctx);
449
0
      if (!hasheq(hash, partial_pack_hash,
450
0
            hash_algo))
451
0
        die("Unexpected checksum for %s "
452
0
            "(disk corruption?)", pack_name);
453
      /*
454
       * Now let's compute the SHA1 of the remainder of the
455
       * pack, which also means making partial_pack_offset
456
       * big enough not to matter anymore.
457
       */
458
0
      hash_algo->init_fn(&old_hash_ctx);
459
0
      partial_pack_offset = ~partial_pack_offset;
460
0
      partial_pack_offset -= MSB(partial_pack_offset, 1);
461
0
    }
462
0
  }
463
0
  free(buf);
464
465
0
  if (partial_pack_hash)
466
0
    git_hash_final(partial_pack_hash, &old_hash_ctx);
467
0
  git_hash_final(new_pack_hash, &new_hash_ctx);
468
0
  write_or_die(pack_fd, new_pack_hash, hash_algo->rawsz);
469
0
  fsync_component_or_die(FSYNC_COMPONENT_PACK, pack_fd, pack_name);
470
0
}
471
472
char *index_pack_lockfile(struct repository *r, int ip_out, int *is_well_formed)
473
0
{
474
0
  char packname[GIT_MAX_HEXSZ + 6];
475
0
  const int len = r->hash_algo->hexsz + 6;
476
477
  /*
478
   * The first thing we expect from index-pack's output
479
   * is "pack\t%40s\n" or "keep\t%40s\n" (46 bytes) where
480
   * %40s is the newly created pack SHA1 name.  In the "keep"
481
   * case, we need it to remove the corresponding .keep file
482
   * later on.  If we don't get that then tough luck with it.
483
   */
484
0
  if (read_in_full(ip_out, packname, len) == len && packname[len-1] == '\n') {
485
0
    const char *name;
486
487
0
    if (is_well_formed)
488
0
      *is_well_formed = 1;
489
0
    packname[len-1] = 0;
490
0
    if (skip_prefix(packname, "keep\t", &name))
491
0
      return xstrfmt("%s/pack/pack-%s.keep",
492
0
               repo_get_object_directory(r), name);
493
0
    return NULL;
494
0
  }
495
0
  if (is_well_formed)
496
0
    *is_well_formed = 0;
497
0
  return NULL;
498
0
}
499
500
/*
501
 * The per-object header is a pretty dense thing, which is
502
 *  - first byte: low four bits are "size", then three bits of "type",
503
 *    and the high bit is "size continues".
504
 *  - each byte afterwards: low seven bits are size continuation,
505
 *    with the high bit being "size continues"
506
 */
507
int encode_in_pack_object_header(unsigned char *hdr, int hdr_len,
508
         enum object_type type, uintmax_t size)
509
0
{
510
0
  int n = 1;
511
0
  unsigned char c;
512
513
0
  if (type < OBJ_COMMIT || type > OBJ_REF_DELTA)
514
0
    die("bad type %d", type);
515
516
0
  c = (type << 4) | (size & 15);
517
0
  size >>= 4;
518
0
  while (size) {
519
0
    if (n == hdr_len)
520
0
      die("object size is too enormous to format");
521
0
    *hdr++ = c | 0x80;
522
0
    c = size & 0x7f;
523
0
    size >>= 7;
524
0
    n++;
525
0
  }
526
0
  *hdr = c;
527
0
  return n;
528
0
}
529
530
struct hashfile *create_tmp_packfile(struct repository *repo,
531
             char **pack_tmp_name)
532
0
{
533
0
  struct strbuf tmpname = STRBUF_INIT;
534
0
  int fd;
535
536
0
  fd = odb_mkstemp(repo->objects, &tmpname, "pack/tmp_pack_XXXXXX");
537
0
  *pack_tmp_name = strbuf_detach(&tmpname, NULL);
538
0
  return hashfd(repo->hash_algo, fd, *pack_tmp_name);
539
0
}
540
541
static void rename_tmp_packfile(struct repository *repo,
542
        struct strbuf *name_prefix, const char *source,
543
        const char *ext)
544
0
{
545
0
  size_t name_prefix_len = name_prefix->len;
546
547
0
  strbuf_addstr(name_prefix, ext);
548
0
  if (finalize_object_file(repo, source, name_prefix->buf))
549
0
    die("unable to rename temporary file to '%s'",
550
0
        name_prefix->buf);
551
0
  strbuf_setlen(name_prefix, name_prefix_len);
552
0
}
553
554
void rename_tmp_packfile_idx(struct repository *repo,
555
           struct strbuf *name_buffer,
556
           char **idx_tmp_name)
557
0
{
558
0
  rename_tmp_packfile(repo, name_buffer, *idx_tmp_name, "idx");
559
0
}
560
561
void stage_tmp_packfiles(struct repository *repo,
562
       struct strbuf *name_buffer,
563
       const char *pack_tmp_name,
564
       struct pack_idx_entry **written_list,
565
       uint32_t nr_written,
566
       struct packing_data *to_pack,
567
       struct pack_idx_option *pack_idx_opts,
568
       unsigned char hash[],
569
       char **idx_tmp_name)
570
0
{
571
0
  char *rev_tmp_name = NULL;
572
0
  char *mtimes_tmp_name = NULL;
573
574
0
  if (adjust_shared_perm(repo, pack_tmp_name))
575
0
    die_errno("unable to make temporary pack file readable");
576
577
0
  *idx_tmp_name = (char *)write_idx_file(repo, NULL, written_list,
578
0
                 nr_written, pack_idx_opts, hash);
579
0
  if (adjust_shared_perm(repo, *idx_tmp_name))
580
0
    die_errno("unable to make temporary index file readable");
581
582
0
  rev_tmp_name = write_rev_file(repo, NULL, written_list, nr_written,
583
0
              hash, pack_idx_opts->flags);
584
585
0
  if (pack_idx_opts->flags & WRITE_MTIMES) {
586
0
    mtimes_tmp_name = write_mtimes_file(repo, to_pack,
587
0
                written_list, nr_written,
588
0
                hash);
589
0
  }
590
591
0
  rename_tmp_packfile(repo, name_buffer, pack_tmp_name, "pack");
592
0
  if (rev_tmp_name)
593
0
    rename_tmp_packfile(repo, name_buffer, rev_tmp_name, "rev");
594
0
  if (mtimes_tmp_name)
595
0
    rename_tmp_packfile(repo, name_buffer, mtimes_tmp_name, "mtimes");
596
597
0
  free(rev_tmp_name);
598
0
  free(mtimes_tmp_name);
599
0
}
600
601
void write_promisor_file(const char *promisor_name, struct ref **sought, int nr_sought)
602
0
{
603
0
  int i, err;
604
0
  FILE *output = xfopen(promisor_name, "w");
605
606
0
  for (i = 0; i < nr_sought; i++)
607
0
    fprintf(output, "%s %s\n", oid_to_hex(&sought[i]->old_oid),
608
0
      sought[i]->name);
609
610
0
  err = ferror(output);
611
0
  err |= fclose(output);
612
0
  if (err)
613
0
    die(_("could not write '%s' promisor file"), promisor_name);
614
0
}