]> git.ipfire.org Git - thirdparty/git.git/commitdiff
cat-file: add %(objectmode) atom
authorVictoria Dye <vdye@github.com>
Mon, 2 Jun 2025 18:55:54 +0000 (18:55 +0000)
committerJunio C Hamano <gitster@pobox.com>
Tue, 3 Jun 2025 19:08:58 +0000 (12:08 -0700)
Add a formatting atom, used with the --batch-check/--batch-command options,
that prints the octal representation of the object mode if a given revision
includes that information, e.g. one that follows the format
<tree-ish>:<path>. If the mode information does not exist, an empty string
is printed instead.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Victoria Dye <vdye@github.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/git-cat-file.adoc
builtin/cat-file.c
t/t1006-cat-file.sh

index cde79ad242bb778b69e8fd0c6592089979708e3f..5c002c0499e482da3223706e8f2ba2893061e77d 100644 (file)
@@ -307,6 +307,11 @@ newline. The available atoms are:
 `objecttype`::
        The type of the object (the same as `cat-file -t` reports).
 
+`objectmode`::
+       If the specified object has mode information (such as a tree or
+       index entry), the mode expressed as an octal integer. Otherwise,
+       empty string.
+
 `objectsize`::
        The size, in bytes, of the object (the same as `cat-file -s`
        reports).
index 67a5ff2b9ebd29d7d2bad988c44abc885dd9f44c..b11576756bccbbc739e3991e27b08e64bfa16228 100644 (file)
@@ -275,6 +275,7 @@ struct expand_data {
        struct object_id oid;
        enum object_type type;
        unsigned long size;
+       unsigned short mode;
        off_t disk_size;
        const char *rest;
        struct object_id delta_base_oid;
@@ -306,6 +307,7 @@ struct expand_data {
         */
        unsigned skip_object_info : 1;
 };
+#define EXPAND_DATA_INIT  { .mode = S_IFINVALID }
 
 static int is_atom(const char *atom, const char *s, int slen)
 {
@@ -345,6 +347,9 @@ static int expand_atom(struct strbuf *sb, const char *atom, int len,
                else
                        strbuf_addstr(sb,
                                      oid_to_hex(&data->delta_base_oid));
+       } else if (is_atom("objectmode", atom, len)) {
+               if (!data->mark_query && !(S_IFINVALID == data->mode))
+                       strbuf_addf(sb, "%06o", data->mode);
        } else
                return 0;
        return 1;
@@ -613,6 +618,7 @@ static void batch_one_object(const char *obj_name,
                goto out;
        }
 
+       data->mode = ctx.mode;
        batch_object_write(obj_name, scratch, opt, data, NULL, 0);
 
 out:
@@ -866,7 +872,7 @@ static int batch_objects(struct batch_options *opt)
 {
        struct strbuf input = STRBUF_INIT;
        struct strbuf output = STRBUF_INIT;
-       struct expand_data data;
+       struct expand_data data = EXPAND_DATA_INIT;
        int save_warning;
        int retval = 0;
 
@@ -875,7 +881,6 @@ static int batch_objects(struct batch_options *opt)
         * object_info to be handed to oid_object_info_extended for each
         * object.
         */
-       memset(&data, 0, sizeof(data));
        data.mark_query = 1;
        expand_format(&output,
                      opt->format ? opt->format : DEFAULT_FORMAT,
index 7c9512a6b439e245cfa563cb87e7834831554f62..97052b3f31f1787d04ee1efe038a18c50c0c96ad 100755 (executable)
@@ -114,10 +114,11 @@ strlen () {
 run_tests () {
     type=$1
     object_name="$2"
-    size=$3
-    content=$4
-    pretty_content=$5
-    oid=${6:-"$object_name"}
+    mode=$3
+    size=$4
+    content=$5
+    pretty_content=$6
+    oid=${7:-"$object_name"}
 
     batch_output="$oid $type $size
 $content"
@@ -209,6 +210,12 @@ $content"
        test_cmp expect actual
     '
 
+    test_expect_success '--batch-check with %(objectmode)' '
+       echo "$mode $oid" >expect &&
+       echo $object_name | git cat-file --batch-check="%(objectmode) %(objectname)" >actual &&
+       test_cmp expect actual
+    '
+
     test -z "$content" ||
     test_expect_success "--batch without type ($type)" '
        {
@@ -247,8 +254,7 @@ test_expect_success "setup" '
 
 run_blob_tests () {
     oid=$1
-
-    run_tests 'blob' $oid $hello_size "$hello_content" "$hello_content"
+    run_tests 'blob' $oid "" $hello_size "$hello_content" "$hello_content"
 
     test_expect_success '--batch-command --buffer with flush for blob info' '
        echo "$oid blob $hello_size" >expect &&
@@ -286,12 +292,12 @@ tree_compat_size=$((2 * $(test_oid --hash=compat rawsz) + 13 + 24))
 tree_pretty_content="100644 blob $hello_oid    hello${LF}100755 blob $hello_oid        path with spaces${LF}"
 tree_compat_pretty_content="100644 blob $hello_compat_oid      hello${LF}100755 blob $hello_compat_oid path with spaces${LF}"
 
-run_tests 'tree' $tree_oid $tree_size "" "$tree_pretty_content"
-run_tests 'tree' $tree_compat_oid $tree_compat_size "" "$tree_compat_pretty_content"
-run_tests 'blob' "$tree_oid:hello" $hello_size "" "$hello_content" $hello_oid
-run_tests 'blob' "$tree_compat_oid:hello" $hello_size "" "$hello_content" $hello_compat_oid
-run_tests 'blob' "$tree_oid:path with spaces" $hello_size "" "$hello_content" $hello_oid
-run_tests 'blob' "$tree_compat_oid:path with spaces" $hello_size "" "$hello_content" $hello_compat_oid
+run_tests 'tree' $tree_oid "" $tree_size "" "$tree_pretty_content"
+run_tests 'tree' $tree_compat_oid "" $tree_compat_size "" "$tree_compat_pretty_content"
+run_tests 'blob' "$tree_oid:hello" "100644" $hello_size "" "$hello_content" $hello_oid
+run_tests 'blob' "$tree_compat_oid:hello" "100644" $hello_size "" "$hello_content" $hello_compat_oid
+run_tests 'blob' "$tree_oid:path with spaces" "100755" $hello_size "" "$hello_content" $hello_oid
+run_tests 'blob' "$tree_compat_oid:path with spaces" "100755" $hello_size "" "$hello_content" $hello_compat_oid
 
 commit_message="Initial commit"
 commit_oid=$(echo_without_newline "$commit_message" | git commit-tree $tree_oid)
@@ -310,8 +316,8 @@ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
 
 $commit_message"
 
-run_tests 'commit' $commit_oid $commit_size "$commit_content" "$commit_content"
-run_tests 'commit' $commit_compat_oid $commit_compat_size "$commit_compat_content" "$commit_compat_content"
+run_tests 'commit' $commit_oid "" $commit_size "$commit_content" "$commit_content"
+run_tests 'commit' $commit_compat_oid "" $commit_compat_size "$commit_compat_content" "$commit_compat_content"
 
 tag_header_without_oid="type blob
 tag hellotag
@@ -334,8 +340,8 @@ tag_size=$(strlen "$tag_content")
 tag_compat_oid=$(git rev-parse --output-object-format=$test_compat_hash_algo $tag_oid)
 tag_compat_size=$(strlen "$tag_compat_content")
 
-run_tests 'tag' $tag_oid $tag_size "$tag_content" "$tag_content"
-run_tests 'tag' $tag_compat_oid $tag_compat_size "$tag_compat_content" "$tag_compat_content"
+run_tests 'tag' $tag_oid "" $tag_size "$tag_content" "$tag_content"
+run_tests 'tag' $tag_compat_oid "" $tag_compat_size "$tag_compat_content" "$tag_compat_content"
 
 test_expect_success "Reach a blob from a tag pointing to it" '
        echo_without_newline "$hello_content" >expect &&