Taylor Blau <me@xxxxxxxxxxxx> writes: > When performing a garbage collection operation on a repository with > unreachable objects, Git makes its decision on what to do with those > object(s) bed on how recent the objects are or not. Generally speaking, s/bed/based/ ? > +gc.recentObjectsHook:: > + When considering whether or not to remove an object (either when > + generating a cruft pack or storing unreachable objects as > + loose), use the shell to execute the specified command(s). > + Interpret their output as object IDs which Git will consider as > + "recent", regardless of their age. By treating their mtimes as > + "now", any objects (and their descendants) mentioned in the > + output will be kept regardless of their true age. Thanks! I think this version will be clear to prospective users. > +static int run_one_gc_recent_objects_hook(struct oidset *set, > + const char *args) > +{ > + struct child_process cmd = CHILD_PROCESS_INIT; > + struct strbuf buf = STRBUF_INIT; > + FILE *out; > + int ret = 0; > + > + cmd.use_shell = 1; > + cmd.out = -1; > + > + strvec_push(&cmd.args, args); > + > + if (start_command(&cmd)) > + return -1; > + > + out = xfdopen(cmd.out, "r"); > + while (strbuf_getline(&buf, out) != EOF) { > + struct object_id oid; > + const char *rest; > + > + if (parse_oid_hex(buf.buf, &oid, &rest) || *rest) { > + ret = error(_("invalid extra cruft tip: '%s'"), buf.buf); To be consistent with the other error message, perhaps s/extra cruft tip/additional recent object/? > +static void load_gc_recent_objects(struct recent_data *data) > +{ > + const struct string_list *programs; > + int ret = 0; > + size_t i; > + > + data->extra_recent_oids_loaded = 1; > + > + if (git_config_get_string_multi("gc.recentobjectshook", &programs)) > + return; > + > + for (i = 0; i < programs->nr; i++) { > + ret = run_one_gc_recent_objects_hook(&data->extra_recent_oids, > + programs->items[i].string); > + if (ret) > + die(_("unable to enumerate additional recent objects")); This error message to be exact. > +test_expect_success 'gc.recentObjectsHook' ' > + git init repo && > + test_when_finished "rm -fr repo" && > + ( > + cd repo && > + > + # Create a handful of objects. > + # > + # - one reachable commit, "base", designated for the reachable > + # pack > + # - one unreachable commit, "cruft.discard", which is marked > + # for deletion > + # - one unreachable commit, "cruft.old", which would be marked > + # for deletion, but is rescued as an extra cruft tip Perhaps we intended to drop "cruft tips" in the test comments too? e.g. here and.. > +test_expect_success 'multi-valued gc.recentObjectsHook' ' > + git init repo && > + test_when_finished "rm -fr repo" && > + ( > + cd repo && > + > + test_commit base && > + git branch -M main && > + > + git checkout --orphan cruft.a && > + git rm -fr . && > + test_commit --no-tag cruft.a && > + cruft_a="$(git rev-parse HEAD)" && > + > + git checkout --orphan cruft.b && > + git rm -fr . && > + test_commit --no-tag cruft.b && > + cruft_b="$(git rev-parse HEAD)" && > + > + git checkout main && > + git branch -D cruft.a cruft.b && > + git reflog expire --all --expire=all && > + > + echo "echo $cruft_a" | write_script extra-tips.a && > + echo "echo $cruft_b" | write_script extra-tips.b && > + echo "false" | write_script extra-tips.c && > + > + git rev-list --objects --no-object-names $cruft_a $cruft_b \ > + >cruft.raw && > + sort cruft.raw >cruft.expect && > + > + # ensure that each extra cruft tip is saved by its here. Aside from those trivial points, everything looks good.