reachable: add options to add_unseen_recent_objects_to_traversal

This function behaves very similarly to what we will need in pack-objects in order to implement cruft packs with expiration. But it is lacking a couple of things. Namely, it needs: - a mechanism to communicate the timestamps of individual recent objects to some external caller - and, in the case of packed objects, our future caller will also want to know the originating pack, as well as the offset within that pack at which the object can be found - finally, it needs a way to skip over packs which are marked as kept in-core. To address the first two, add a callback interface in this patch which reports the time of each recent object, as well as a (packed_git, off_t) pair for packed objects. Likewise, add a new option to the packed object iterators to skip over packs which are marked as kept in core. This option will become implicitly tested in a future patch. Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Taylor Blau committed May 20, 2022 at 19:17 UTC 2fb90409b8133803bae89773ac9a9db629443dc6
3 files changed +52 -10
builtin/pack-objects.c
+1 -1
@@ -3957,7 +3957,7 @@ static void get_object_list(struct rev_info *revs, int ac, const char **av)
3957 if (unpack_unreachable_expiration) {
3958 revs->ignore_missing_links = 1;
3959 if (add_unseen_recent_objects_to_traversal(revs,
3960 - unpack_unreachable_expiration))
3960 + unpack_unreachable_expiration, NULL, 0))
3961 die(_("unable to add recent objects"));
3962 if (prepare_revision_walk(revs))
3963 die(_("revision walk setup failed"));
reachable.c
+43 -8
@@ -60,9 +60,13 @@ static void mark_commit(struct commit *c, void *data)
60 struct recent_data {
61 struct rev_info *revs;
62 timestamp_t timestamp;
63 + report_recent_object_fn *cb;
64 + int ignore_in_core_kept_packs;
65 };
66
67 static void add_recent_object(const struct object_id *oid,
68 + struct packed_git *pack,
69 + off_t offset,
70 timestamp_t mtime,
71 struct recent_data *data)
72 {
@@ -103,13 +107,29 @@ static void add_recent_object(const struct object_id *oid,
107 die("unable to lookup %s", oid_to_hex(oid));
108
109 add_pending_object(data->revs, obj, "");
110 + if (data->cb)
111 + data->cb(obj, pack, offset, mtime);
112 +}
113 +
114 +static int want_recent_object(struct recent_data *data,
115 + const struct object_id *oid)
116 +{
117 + if (data->ignore_in_core_kept_packs &&
118 + has_object_kept_pack(oid, IN_CORE_KEEP_PACKS))
119 + return 0;
120 + return 1;
121 }
122
123 static int add_recent_loose(const struct object_id *oid,
124 const char *path, void *data)
125 {
126 struct stat st;
112 - struct object *obj = lookup_object(the_repository, oid);
127 + struct object *obj;
128 +
129 + if (!want_recent_object(data, oid))
130 + return 0;
131 +
132 + obj = lookup_object(the_repository, oid);
133
134 if (obj && obj->flags & SEEN)
135 return 0;
@@ -126,7 +146,7 @@ static int add_recent_loose(const struct object_id *oid,
146 return error_errno("unable to stat %s", oid_to_hex(oid));
147 }
148
129 - add_recent_object(oid, st.st_mtime, data);
149 + add_recent_object(oid, NULL, 0, st.st_mtime, data);
150 return 0;
151 }
152
@@ -134,29 +154,43 @@ static int add_recent_packed(const struct object_id *oid,
154 struct packed_git *p, uint32_t pos,
155 void *data)
156 {
137 - struct object *obj = lookup_object(the_repository, oid);
157 + struct object *obj;
158 +
159 + if (!want_recent_object(data, oid))
160 + return 0;
161 +
162 + obj = lookup_object(the_repository, oid);
163
164 if (obj && obj->flags & SEEN)
165 return 0;
141 - add_recent_object(oid, p->mtime, data);
166 + add_recent_object(oid, p, nth_packed_object_offset(p, pos), p->mtime, data);
167 return 0;
168 }
169
170 int add_unseen_recent_objects_to_traversal(struct rev_info *revs,
146 - timestamp_t timestamp)
171 + timestamp_t timestamp,
172 + report_recent_object_fn *cb,
173 + int ignore_in_core_kept_packs)
174 {
175 struct recent_data data;
176 + enum for_each_object_flags flags;
177 int r;
178
179 data.revs = revs;
180 data.timestamp = timestamp;
181 + data.cb = cb;
182 + data.ignore_in_core_kept_packs = ignore_in_core_kept_packs;
183
184 r = for_each_loose_object(add_recent_loose, &data,
185 FOR_EACH_OBJECT_LOCAL_ONLY);
186 if (r)
187 return r;
158 - return for_each_packed_object(add_recent_packed, &data,
159 - FOR_EACH_OBJECT_LOCAL_ONLY);
188 +
189 + flags = FOR_EACH_OBJECT_LOCAL_ONLY | FOR_EACH_OBJECT_PACK_ORDER;
190 + if (ignore_in_core_kept_packs)
191 + flags |= FOR_EACH_OBJECT_SKIP_IN_CORE_KEPT_PACKS;
192 +
193 + return for_each_packed_object(add_recent_packed, &data, flags);
194 }
195
196 static int mark_object_seen(const struct object_id *oid,
@@ -217,7 +251,8 @@ void mark_reachable_objects(struct rev_info *revs, int mark_reflog,
251
252 if (mark_recent) {
253 revs->ignore_missing_links = 1;
220 - if (add_unseen_recent_objects_to_traversal(revs, mark_recent))
254 + if (add_unseen_recent_objects_to_traversal(revs, mark_recent,
255 + NULL, 0))
256 die("unable to mark recent objects");
257 if (prepare_revision_walk(revs))
258 die("revision walk setup failed");
reachable.h
+8 -1
@@ -1,11 +1,18 @@
1 #ifndef REACHEABLE_H
2 #define REACHEABLE_H
3
4 +#include "object.h"
5 +
6 struct progress;
7 struct rev_info;
8
9 +typedef void report_recent_object_fn(const struct object *, struct packed_git *,
10 + off_t, time_t);
11 +
12 int add_unseen_recent_objects_to_traversal(struct rev_info *revs,
8 - timestamp_t timestamp);
13 + timestamp_t timestamp,
14 + report_recent_object_fn cb,
15 + int ignore_in_core_kept_packs);
16 void mark_reachable_objects(struct rev_info *revs, int mark_reflog,
17 timestamp_t mark_recent, struct progress *);
18