shallow: offer to prune only non-existing entries

The `prune_shallow()` function wants a full reachability check to be completed before it goes to work, to ensure that all unreachable entries are removed from the shallow file. However, in the upcoming patch we do not even want to go that far. We really only need to remove entries corresponding to pruned commits, i.e. to commits that no longer exist. Let's support that use case. Rather than extending the signature of `prune_shallow()` to accept another Boolean, let's turn it into a bit field and declare constants, for readability. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Johannes Schindelin committed Oct 24, 2018 at 08:56 UTC 2588f6ed8bd4e31c1ea1ae35f9f668452b46f1ef
3 files changed +21 -8
builtin/prune.c
+1 -1
@@ -161,7 +161,7 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
161 free(s);
162
163 if (is_repository_shallow(the_repository))
164 - prune_shallow(show_only);
164 + prune_shallow(show_only ? PRUNE_SHOW_ONLY : 0);
165
166 return 0;
167 }
commit.h
+3 -1
@@ -255,7 +255,9 @@ extern void assign_shallow_commits_to_refs(struct shallow_info *info,
255 uint32_t **used,
256 int *ref_status);
257 extern int delayed_reachability_test(struct shallow_info *si, int c);
258 -extern void prune_shallow(int show_only);
258 +#define PRUNE_SHOW_ONLY 1
259 +#define PRUNE_QUICK 2
260 +extern void prune_shallow(unsigned options);
261 extern struct trace_key trace_shallow;
262
263 int is_descendant_of(struct commit *, struct commit_list *);
shallow.c
+17 -6
@@ -246,6 +246,7 @@ static void check_shallow_file_for_update(struct repository *r)
246
247 #define SEEN_ONLY 1
248 #define VERBOSE 2
249 +#define QUICK 4
250
251 struct write_shallow_data {
252 struct strbuf *out;
@@ -260,7 +261,10 @@ static int write_one_shallow(const struct commit_graft *graft, void *cb_data)
261 const char *hex = oid_to_hex(&graft->oid);
262 if (graft->nr_parent != -1)
263 return 0;
263 - if (data->flags & SEEN_ONLY) {
264 + if (data->flags & QUICK) {
265 + if (!has_object_file(&graft->oid))
266 + return 0;
267 + } else if (data->flags & SEEN_ONLY) {
268 struct commit *c = lookup_commit(the_repository, &graft->oid);
269 if (!c || !(c->object.flags & SEEN)) {
270 if (data->flags & VERBOSE)
@@ -370,16 +374,23 @@ void advertise_shallow_grafts(int fd)
374
375 /*
376 * mark_reachable_objects() should have been run prior to this and all
373 - * reachable commits marked as "SEEN".
377 + * reachable commits marked as "SEEN", except when quick_prune is non-zero,
378 + * in which case lines are excised from the shallow file if they refer to
379 + * commits that do not exist (any longer).
380 */
375 -void prune_shallow(int show_only)
381 +void prune_shallow(unsigned options)
382 {
383 struct lock_file shallow_lock = LOCK_INIT;
384 struct strbuf sb = STRBUF_INIT;
385 + unsigned flags = SEEN_ONLY;
386 int fd;
387
381 - if (show_only) {
382 - write_shallow_commits_1(&sb, 0, NULL, SEEN_ONLY | VERBOSE);
388 + if (options & PRUNE_QUICK)
389 + flags |= QUICK;
390 +
391 + if (options & PRUNE_SHOW_ONLY) {
392 + flags |= VERBOSE;
393 + write_shallow_commits_1(&sb, 0, NULL, flags);
394 strbuf_release(&sb);
395 return;
396 }
@@ -387,7 +398,7 @@ void prune_shallow(int show_only)
398 git_path_shallow(the_repository),
399 LOCK_DIE_ON_ERROR);
400 check_shallow_file_for_update(the_repository);
390 - if (write_shallow_commits_1(&sb, 0, NULL, SEEN_ONLY)) {
401 + if (write_shallow_commits_1(&sb, 0, NULL, flags)) {
402 if (write_in_full(fd, sb.buf, sb.len) < 0)
403 die_errno("failed to write to %s",
404 get_lock_file_path(&shallow_lock));