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 |