Coverage Report

Created: 2026-10-17 07:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/git/packfile.h
Line
Count
Source
1
#ifndef PACKFILE_H
2
#define PACKFILE_H
3
4
#include "list.h"
5
#include "object.h"
6
#include "odb.h"
7
#include "odb/source-files.h"
8
#include "odb/source-packed.h"
9
#include "oidset.h"
10
#include "packfile-list.h"
11
#include "repository.h"
12
13
/* in odb.h */
14
struct object_info;
15
struct odb_stream;
16
17
struct packed_git {
18
  struct pack_window *windows;
19
  off_t pack_size;
20
  const void *index_data;
21
  size_t index_size;
22
  uint32_t num_objects;
23
  size_t crc_offset;
24
  struct oidset bad_objects;
25
  int index_version;
26
  time_t mtime;
27
  int pack_fd;
28
  int index;              /* for builtin/pack-objects.c */
29
  unsigned pack_local:1,
30
     pack_keep:1,
31
     pack_keep_in_core:1,
32
     pack_keep_in_core_open:1,
33
     freshened:1,
34
     do_not_close:1,
35
     pack_promisor:1,
36
     multi_pack_index:1,
37
     is_cruft:1;
38
  unsigned char hash[GIT_MAX_RAWSZ];
39
  struct revindex_entry *revindex;
40
  const uint32_t *revindex_data;
41
  const uint32_t *revindex_map;
42
  size_t revindex_size;
43
  /*
44
   * mtimes_map points at the beginning of the memory mapped region of
45
   * this pack's corresponding .mtimes file, and mtimes_size is the size
46
   * of that .mtimes file
47
   */
48
  const uint32_t *mtimes_map;
49
  size_t mtimes_size;
50
51
  /* repo denotes the repository this packfile belongs to */
52
  struct repository *repo;
53
54
  /* something like ".git/objects/pack/xxxxx.pack" */
55
  char pack_name[FLEX_ARRAY]; /* more */
56
};
57
58
/*
59
 * Add the pack to the store so that contained objects become accessible via
60
 * the store. This moves ownership into the store.
61
 */
62
void packfile_store_add_pack(struct odb_source_packed *store,
63
           struct packed_git *pack);
64
65
/*
66
 * Get all packs managed by the given store, including packfiles that are
67
 * referenced by multi-pack indices.
68
 */
69
struct packfile_list_entry *packfile_store_get_packs(struct odb_source_packed *store);
70
71
struct repo_for_each_pack_data {
72
  struct odb_source *source;
73
  struct packfile_list_entry *entry;
74
};
75
76
static inline struct repo_for_each_pack_data repo_for_eack_pack_data_init(struct repository *repo)
77
0
{
78
0
  struct repo_for_each_pack_data data = { 0 };
79
80
0
  for (struct odb_source *source = repo->objects->sources; source; source = source->next) {
81
0
    struct odb_source_files *files = odb_source_files_downcast(source);
82
0
    struct packfile_list_entry *entry = packfile_store_get_packs(files->packed);
83
0
    if (!entry)
84
0
      continue;
85
0
    data.source = source;
86
0
    data.entry = entry;
87
0
    break;
88
0
  }
89
90
0
  return data;
91
0
}
Unexecuted instantiation: run-command.c:repo_for_eack_pack_data_init
Unexecuted instantiation: tag.c:repo_for_eack_pack_data_init
Unexecuted instantiation: diff.c:repo_for_eack_pack_data_init
Unexecuted instantiation: list-objects.c:repo_for_eack_pack_data_init
Unexecuted instantiation: object-file.c:repo_for_eack_pack_data_init
Unexecuted instantiation: source.c:repo_for_eack_pack_data_init
Unexecuted instantiation: source-files.c:repo_for_eack_pack_data_init
Unexecuted instantiation: source-packed.c:repo_for_eack_pack_data_init
Unexecuted instantiation: pack-bitmap.c:repo_for_eack_pack_data_init
Unexecuted instantiation: pack-check.c:repo_for_eack_pack_data_init
Unexecuted instantiation: pack-objects.c:repo_for_eack_pack_data_init
Unexecuted instantiation: pack-revindex.c:repo_for_eack_pack_data_init
Unexecuted instantiation: pack-write.c:repo_for_eack_pack_data_init
Unexecuted instantiation: packfile.c:repo_for_eack_pack_data_init
Unexecuted instantiation: packfile-list.c:repo_for_eack_pack_data_init
Unexecuted instantiation: path.c:repo_for_eack_pack_data_init
Unexecuted instantiation: promisor-remote.c:repo_for_eack_pack_data_init
Unexecuted instantiation: pseudo-merge.c:repo_for_eack_pack_data_init
Unexecuted instantiation: repack.c:repo_for_eack_pack_data_init
Unexecuted instantiation: repack-geometry.c:repo_for_eack_pack_data_init
Unexecuted instantiation: repo-settings.c:repo_for_eack_pack_data_init
Unexecuted instantiation: revision.c:repo_for_eack_pack_data_init
Unexecuted instantiation: commit-graph.c:repo_for_eack_pack_data_init
Unexecuted instantiation: connected.c:repo_for_eack_pack_data_init
Unexecuted instantiation: fetch-pack.c:repo_for_eack_pack_data_init
Unexecuted instantiation: fsck.c:repo_for_eack_pack_data_init
Unexecuted instantiation: midx.c:repo_for_eack_pack_data_init
Unexecuted instantiation: pack-bitmap-write.c:repo_for_eack_pack_data_init
Unexecuted instantiation: pack-mtimes.c:repo_for_eack_pack_data_init
Unexecuted instantiation: transport-helper.c:repo_for_eack_pack_data_init
92
93
static inline void repo_for_each_pack_data_next(struct repo_for_each_pack_data *data)
94
0
{
95
0
  struct odb_source *source;
96
97
0
  data->entry = data->entry->next;
98
0
  if (data->entry)
99
0
    return;
100
101
0
  for (source = data->source->next; source; source = source->next) {
102
0
    struct odb_source_files *files = odb_source_files_downcast(source);
103
0
    struct packfile_list_entry *entry = packfile_store_get_packs(files->packed);
104
0
    if (!entry)
105
0
      continue;
106
0
    data->source = source;
107
0
    data->entry = entry;
108
0
    return;
109
0
  }
110
111
0
  data->source = NULL;
112
0
  data->entry = NULL;
113
0
}
Unexecuted instantiation: run-command.c:repo_for_each_pack_data_next
Unexecuted instantiation: tag.c:repo_for_each_pack_data_next
Unexecuted instantiation: diff.c:repo_for_each_pack_data_next
Unexecuted instantiation: list-objects.c:repo_for_each_pack_data_next
Unexecuted instantiation: object-file.c:repo_for_each_pack_data_next
Unexecuted instantiation: source.c:repo_for_each_pack_data_next
Unexecuted instantiation: source-files.c:repo_for_each_pack_data_next
Unexecuted instantiation: source-packed.c:repo_for_each_pack_data_next
Unexecuted instantiation: pack-bitmap.c:repo_for_each_pack_data_next
Unexecuted instantiation: pack-check.c:repo_for_each_pack_data_next
Unexecuted instantiation: pack-objects.c:repo_for_each_pack_data_next
Unexecuted instantiation: pack-revindex.c:repo_for_each_pack_data_next
Unexecuted instantiation: pack-write.c:repo_for_each_pack_data_next
Unexecuted instantiation: packfile.c:repo_for_each_pack_data_next
Unexecuted instantiation: packfile-list.c:repo_for_each_pack_data_next
Unexecuted instantiation: path.c:repo_for_each_pack_data_next
Unexecuted instantiation: promisor-remote.c:repo_for_each_pack_data_next
Unexecuted instantiation: pseudo-merge.c:repo_for_each_pack_data_next
Unexecuted instantiation: repack.c:repo_for_each_pack_data_next
Unexecuted instantiation: repack-geometry.c:repo_for_each_pack_data_next
Unexecuted instantiation: repo-settings.c:repo_for_each_pack_data_next
Unexecuted instantiation: revision.c:repo_for_each_pack_data_next
Unexecuted instantiation: commit-graph.c:repo_for_each_pack_data_next
Unexecuted instantiation: connected.c:repo_for_each_pack_data_next
Unexecuted instantiation: fetch-pack.c:repo_for_each_pack_data_next
Unexecuted instantiation: fsck.c:repo_for_each_pack_data_next
Unexecuted instantiation: midx.c:repo_for_each_pack_data_next
Unexecuted instantiation: pack-bitmap-write.c:repo_for_each_pack_data_next
Unexecuted instantiation: pack-mtimes.c:repo_for_each_pack_data_next
Unexecuted instantiation: transport-helper.c:repo_for_each_pack_data_next
114
115
/*
116
 * Load and iterate through all packs of the given repository. This helper
117
 * function will yield packfiles from all object sources connected to the
118
 * repository.
119
 */
120
#define repo_for_each_pack(repo, p) \
121
0
  for (struct repo_for_each_pack_data eack_pack_data = repo_for_eack_pack_data_init(repo); \
122
0
       ((p) = (eack_pack_data.entry ? eack_pack_data.entry->pack : NULL)); \
123
0
       repo_for_each_pack_data_next(&eack_pack_data))
124
125
/*
126
 * Open the packfile and add it to the store if it isn't yet known. Returns
127
 * either the newly opened packfile or the preexisting packfile. Returns a
128
 * `NULL` pointer in case the packfile could not be opened.
129
 */
130
struct packed_git *packfile_store_load_pack(struct odb_source_packed *store,
131
              const char *idx_path, int local);
132
133
enum kept_pack_type {
134
  KEPT_PACK_ON_DISK = (1 << 0),
135
  KEPT_PACK_IN_CORE = (1 << 1),
136
  KEPT_PACK_IN_CORE_OPEN = (1 << 2),
137
};
138
139
/*
140
 * Retrieve the cache of kept packs from the given packfile store. Accepts a
141
 * combination of `kept_pack_type` flags. The cache is computed on demand and
142
 * will be recomputed whenever the flags change.
143
 */
144
struct packed_git **packfile_store_get_kept_pack_cache(struct odb_source_packed *store,
145
                   unsigned flags);
146
147
struct pack_window {
148
  struct pack_window *next;
149
  unsigned char *base;
150
  off_t offset;
151
  size_t len;
152
  unsigned int last_used;
153
  unsigned int inuse_cnt;
154
};
155
156
struct pack_entry {
157
  off_t offset;
158
  struct packed_git *p;
159
};
160
161
/*
162
 * Generate the filename to be used for a pack file with checksum "sha1" and
163
 * extension "ext". The result is written into the strbuf "buf", overwriting
164
 * any existing contents. A pointer to buf->buf is returned as a convenience.
165
 *
166
 * Example: odb_pack_name(out, sha1, "idx") => ".git/objects/pack/pack-1234..idx"
167
 */
168
char *odb_pack_name(struct repository *r, struct strbuf *buf,
169
        const unsigned char *hash, const char *ext);
170
171
/*
172
 * Return the basename of the packfile, omitting any containing directory
173
 * (e.g., "pack-1234abcd[...].pack").
174
 */
175
const char *pack_basename(struct packed_git *p);
176
177
/*
178
 * Parse the pack idx file found at idx_path and create a packed_git struct
179
 * which can be used with find_pack_entry_one().
180
 *
181
 * You probably don't want to use this function! It skips most of the normal
182
 * sanity checks (including whether we even have the matching .pack file),
183
 * and does not add the resulting packed_git struct to the internal list of
184
 * packs. You probably want add_packed_git() instead.
185
 */
186
struct packed_git *parse_pack_index(struct repository *r, unsigned char *sha1,
187
            const char *idx_path);
188
189
typedef void each_file_in_pack_dir_fn(const char *full_path, size_t full_path_len,
190
              const char *file_name, void *data);
191
void for_each_file_in_pack_subdir(const char *objdir,
192
          const char *subdir,
193
          each_file_in_pack_dir_fn fn,
194
          void *data);
195
void for_each_file_in_pack_dir(const char *objdir,
196
             each_file_in_pack_dir_fn fn,
197
             void *data);
198
199
/*
200
 * Iterate over all accessible packed objects without respect to reachability.
201
 * By default, this includes both local and alternate packs.
202
 *
203
 * Note that some objects may appear twice if they are found in multiple packs.
204
 * Each pack is visited in an unspecified order. By default, objects within a
205
 * pack are visited in pack-idx order (i.e., sorted by oid).
206
 */
207
typedef int each_packed_object_fn(const struct object_id *oid,
208
          struct packed_git *pack,
209
          uint32_t pos,
210
          void *data);
211
int for_each_object_in_pack(struct packed_git *p,
212
          each_packed_object_fn, void *data,
213
          enum odb_for_each_object_flags flags);
214
215
/* A hook to report invalid files in pack directory */
216
0
#define PACKDIR_FILE_PACK 1
217
0
#define PACKDIR_FILE_IDX 2
218
0
#define PACKDIR_FILE_GARBAGE 4
219
extern void (*report_garbage)(unsigned seen_bits, const char *path);
220
221
void pack_report(struct repository *repo);
222
223
/*
224
 * mmap the index file for the specified packfile (if it is not
225
 * already mmapped).  Return 0 on success.
226
 */
227
int open_pack_index(struct packed_git *);
228
229
/*
230
 * munmap the index file for the specified packfile (if it is
231
 * currently mmapped).
232
 */
233
void close_pack_index(struct packed_git *);
234
235
int close_pack_fd(struct packed_git *p);
236
237
uint32_t get_pack_fanout(struct packed_git *p, uint32_t value);
238
239
struct object_database;
240
241
unsigned char *use_pack(struct packed_git *, struct pack_window **, off_t,
242
      size_t *);
243
void close_pack_windows(struct packed_git *);
244
void close_pack(struct packed_git *);
245
void unuse_pack(struct pack_window **);
246
void clear_delta_base_cache(void);
247
struct packed_git *add_packed_git(struct repository *r, const char *path,
248
          size_t path_len, int local);
249
250
/*
251
 * Unlink the .pack and associated extension files.
252
 * Does not unlink if 'force_delete' is false and the pack-file is
253
 * marked as ".keep".
254
 */
255
void unlink_pack_path(const char *pack_name, int force_delete);
256
257
/*
258
 * Make sure that a pointer access into an mmap'd index file is within bounds,
259
 * and can provide at least 8 bytes of data.
260
 *
261
 * Note that this is only necessary for variable-length segments of the file
262
 * (like the 64-bit extended offset table), as we compare the size to the
263
 * fixed-length parts when we open the file.
264
 */
265
void check_pack_index_ptr(const struct packed_git *p, const void *ptr);
266
267
/*
268
 * Perform binary search on a pack-index for a given oid. Packfile is expected to
269
 * have a valid pack-index.
270
 *
271
 * See 'bsearch_hash' for more information.
272
 */
273
int bsearch_pack(const struct object_id *oid, const struct packed_git *p, uint32_t *result);
274
275
/*
276
 * Write the oid of the nth object within the specified packfile into the first
277
 * parameter. Open the index if it is not already open.  Returns 0 on success,
278
 * negative otherwise.
279
 */
280
int nth_packed_object_id(struct object_id *, struct packed_git *, uint32_t n);
281
282
/*
283
 * Return the offset of the nth object within the specified packfile.
284
 * The index must already be opened.
285
 */
286
off_t nth_packed_object_offset(const struct packed_git *, uint32_t n);
287
288
/*
289
 * If the object named by oid is present in the specified packfile,
290
 * return its offset within the packfile; otherwise, return 0.
291
 */
292
off_t find_pack_entry_one(const struct object_id *oid, struct packed_git *);
293
294
int packfile_fill_entry(struct packed_git *p,
295
      const struct object_id *oid,
296
      struct pack_entry *e,
297
      struct packed_git **bad_pack);
298
299
int is_pack_valid(struct packed_git *);
300
void *unpack_entry(struct repository *r, struct packed_git *, off_t,
301
       enum object_type *, size_t *);
302
size_t unpack_object_header_buffer(const unsigned char *buf, size_t len,
303
           enum object_type *type, size_t *sizep);
304
size_t get_size_from_delta(struct packed_git *, struct pack_window **, off_t);
305
int unpack_object_header(struct packed_git *, struct pack_window **, off_t *, size_t *);
306
off_t get_delta_base(struct packed_git *p, struct pack_window **w_curs,
307
         off_t *curpos, enum object_type type,
308
         off_t delta_obj_offset);
309
310
int packfile_read_object_stream(struct odb_stream **out,
311
        const struct object_id *oid,
312
        struct packed_git *pack,
313
        off_t offset);
314
315
void release_pack_memory(size_t);
316
317
/* global flag to enable extra checks when accessing packed objects */
318
extern int do_check_packed_object_crc;
319
320
/*
321
 * Look up the object info for a specific offset in the packfile.
322
 * Returns zero on success, a negative error code otherwise.
323
 */
324
int packed_object_info(struct odb_source_packed *source,
325
           struct packed_git *pack,
326
           off_t offset, struct object_info *);
327
int packed_object_info_with_index_pos(struct odb_source_packed *source,
328
              struct packed_git *p, off_t obj_offset,
329
              uint32_t *maybe_index_pos, struct object_info *oi);
330
331
void mark_bad_packed_object(struct packed_git *, const struct object_id *);
332
333
int has_object_pack(struct repository *r, const struct object_id *oid);
334
int has_object_kept_pack(struct repository *r, const struct object_id *oid,
335
       unsigned flags);
336
337
/*
338
 * Return 1 if an object in a promisor packfile is or refers to the given
339
 * object, 0 otherwise.
340
 */
341
int is_promisor_object(struct repository *r, const struct object_id *oid);
342
343
/*
344
 * Expose a function for fuzz testing.
345
 *
346
 * load_idx() parses a block of memory as a packfile index and puts the results
347
 * into a struct packed_git.
348
 *
349
 * This function should not be used directly. It is exposed here only so that we
350
 * have a convenient entry-point for fuzz testing. For real uses, you should
351
 * probably use open_pack_index() instead.
352
 */
353
int load_idx(const char *path, const unsigned int hashsz, void *idx_map,
354
       size_t idx_size, struct packed_git *p);
355
356
/*
357
 * Parse a --pack_header option as accepted by index-pack and unpack-objects,
358
 * turning it into the matching bytes we'd find in a pack.
359
 */
360
int parse_pack_header_option(const char *in, unsigned char *out, unsigned int *len);
361
362
#endif