]> git.ipfire.org Git - thirdparty/git.git/commitdiff
rev-list: support NUL-delimited --missing option
authorJustin Tobler <jltobler@gmail.com>
Wed, 19 Mar 2025 18:34:10 +0000 (13:34 -0500)
committerJunio C Hamano <gitster@pobox.com>
Fri, 21 Mar 2025 10:40:03 +0000 (03:40 -0700)
The `--missing={print,print-info}` option for git-rev-list(1) prints
missing objects found while performing the object walk in the form:

        $ git rev-list --missing=print-info <rev>
        ?<oid> [SP <token>=<value>]... LF

Add support for printing missing objects in a NUL-delimited format when
the `-z` option is enabled.

        $ git rev-list -z --missing=print-info <rev>
        <oid> NUL missing=yes NUL [<token>=<value> NUL]...

In this mode, values containing special characters or spaces are printed
as-is without being escaped or quoted. Instead of prefixing the missing
OID with '?', a separate `missing=yes` token/value pair is appended.

Signed-off-by: Justin Tobler <jltobler@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/rev-list-options.adoc
builtin/rev-list.c
t/t6022-rev-list-missing.sh

index 3fc9902d6b8f7af79242930ac220a7311fdec3dc..0e5605a85ef84fc2fb197316dff670c02d1ec205 100644 (file)
@@ -380,10 +380,11 @@ and thus is used to signal the start of a new object record. Examples:
 <OID> NUL
 <OID> NUL path=<path> NUL
 <OID> NUL boundary=yes NUL
+<OID> NUL missing=yes NUL [<token>=<value> NUL]...
 -----------------------------------------------------------------------
 +
-This mode is only compatible with the `--objects` and `--boundary` output
-options.
+This mode is only compatible with the `--objects`, `--boundary`, and
+`--missing` output options.
 endif::git-rev-list[]
 
 History Simplification
index bcb880f10996c6a21ab5ef00cbd18136a7945c61..e6ee3f82ee5d540452c56f3bd538aa154777a7b4 100644 (file)
@@ -136,24 +136,37 @@ static void print_missing_object(struct missing_objects_map_entry *entry,
 {
        struct strbuf sb = STRBUF_INIT;
 
+       if (line_term)
+               printf("?%s", oid_to_hex(&entry->entry.oid));
+       else
+               printf("%s%cmissing=yes", oid_to_hex(&entry->entry.oid),
+                      info_term);
+
        if (!print_missing_info) {
-               printf("?%s\n", oid_to_hex(&entry->entry.oid));
+               putchar(line_term);
                return;
        }
 
        if (entry->path && *entry->path) {
-               struct strbuf path = STRBUF_INIT;
+               strbuf_addf(&sb, "%cpath=", info_term);
+
+               if (line_term) {
+                       struct strbuf path = STRBUF_INIT;
 
-               strbuf_addstr(&sb, " path=");
-               quote_path(entry->path, NULL, &path, QUOTE_PATH_QUOTE_SP);
-               strbuf_addbuf(&sb, &path);
+                       quote_path(entry->path, NULL, &path, QUOTE_PATH_QUOTE_SP);
+                       strbuf_addbuf(&sb, &path);
 
-               strbuf_release(&path);
+                       strbuf_release(&path);
+               } else {
+                       strbuf_addstr(&sb, entry->path);
+               }
        }
        if (entry->type)
-               strbuf_addf(&sb, " type=%s", type_name(entry->type));
+               strbuf_addf(&sb, "%ctype=%s", info_term, type_name(entry->type));
+
+       fwrite(sb.buf, sizeof(char), sb.len, stdout);
+       putchar(line_term);
 
-       printf("?%s%s\n", oid_to_hex(&entry->entry.oid), sb.buf);
        strbuf_release(&sb);
 }
 
@@ -783,7 +796,7 @@ int cmd_rev_list(int argc,
                if (revs.graph || revs.verbose_header || show_disk_usage ||
                    info.show_timestamp || info.header_prefix || bisect_list ||
                    use_bitmap_index || revs.edge_hint || revs.left_right ||
-                   revs.cherry_mark || arg_missing_action)
+                   revs.cherry_mark)
                        die(_("-z option used with unsupported option"));
        }
 
index 3e2790d4c826d8e6219b55c95edb8aaf26e4c73a..08e92dd002571926c1b507c317a86a5bcb06f076 100755 (executable)
@@ -198,4 +198,35 @@ do
        '
 done
 
+test_expect_success "-z nul-delimited --missing" '
+       test_when_finished rm -rf repo &&
+
+       git init repo &&
+       (
+               cd repo &&
+               git commit --allow-empty -m first &&
+
+               path="foo bar" &&
+               echo foobar >"$path" &&
+               git add -A &&
+               git commit -m second &&
+
+               oid=$(git rev-parse "HEAD:$path") &&
+               type="$(git cat-file -t $oid)" &&
+
+               obj_path=".git/objects/$(test_oid_to_path $oid)" &&
+
+               git rev-list -z --objects --no-object-names \
+                       HEAD ^"$oid" >expect &&
+               printf "%s\0missing=yes\0path=%s\0type=%s\0" "$oid" "$path" \
+                       "$type" >>expect &&
+
+               mv "$obj_path" "$obj_path.hidden" &&
+               git rev-list -z --objects --no-object-names \
+                       --missing=print-info HEAD >actual &&
+
+               test_cmp expect actual
+       )
+'
+
 test_done