load_subtree(): check earlier whether an internal node is a tree entry
[gitweb.git] / notes.c
diff --git a/notes.c b/notes.c
index c33aead864a691c251f1050046f05a4cbfe214e6..61a5001fc069debdff9bffe453a0ae000eac5319 100644 (file)
--- a/notes.c
+++ b/notes.c
@@ -433,30 +433,43 @@ static void load_subtree(struct notes_tree *t, struct leaf_node *subtree,
        while (tree_entry(&desc, &entry)) {
                unsigned char type;
                struct leaf_node *l;
-               int len, path_len = strlen(entry.path);
+               int path_len = strlen(entry.path);
+
+               if (path_len == 2 * (GIT_SHA1_RAWSZ - prefix_len)) {
+                       /* This is potentially the remainder of the SHA-1 */
+                       if (get_oid_hex_segment(entry.path, path_len,
+                                               object_oid.hash + prefix_len,
+                                               GIT_SHA1_RAWSZ - prefix_len) < 0)
+                               goto handle_non_note; /* entry.path is not a SHA1 */
+
+                       type = PTR_TYPE_NOTE;
+                       l = (struct leaf_node *)
+                               xcalloc(1, sizeof(struct leaf_node));
+                       oidcpy(&l->key_oid, &object_oid);
+                       oidcpy(&l->val_oid, entry.oid);
+               } else if (path_len == 2) {
+                       /* This is potentially an internal node */
+
+                       if (!S_ISDIR(entry.mode))
+                               /* internal nodes must be trees */
+                               goto handle_non_note;
+
+                       if (get_oid_hex_segment(entry.path, 2,
+                                               object_oid.hash + prefix_len,
+                                               GIT_SHA1_RAWSZ - prefix_len) < 0)
+                               goto handle_non_note; /* entry.path is not a SHA1 */
 
-               len = get_oid_hex_segment(entry.path, path_len,
-                               object_oid.hash + prefix_len, GIT_SHA1_RAWSZ - prefix_len);
-               if (len < 0)
-                       goto handle_non_note; /* entry.path is not a SHA1 */
-               len += prefix_len;
-
-               /*
-                * If object SHA1 is complete (len == 20), assume note object
-                * If object SHA1 is incomplete (len < 20), and current
-                * component consists of 2 hex chars, assume note subtree
-                */
-               type = PTR_TYPE_NOTE;
-               l = (struct leaf_node *)
-                       xcalloc(1, sizeof(struct leaf_node));
-               oidcpy(&l->key_oid, &object_oid);
-               oidcpy(&l->val_oid, entry.oid);
-               if (len < GIT_SHA1_RAWSZ) {
-                       if (!S_ISDIR(entry.mode) || path_len != 2)
-                               goto handle_non_note; /* not subtree */
-                       l->key_oid.hash[KEY_INDEX] = (unsigned char) len;
                        type = PTR_TYPE_SUBTREE;
+                       l = (struct leaf_node *)
+                               xcalloc(1, sizeof(struct leaf_node));
+                       oidcpy(&l->key_oid, &object_oid);
+                       oidcpy(&l->val_oid, entry.oid);
+                       l->key_oid.hash[KEY_INDEX] = (unsigned char) (prefix_len + 1);
+               } else {
+                       /* This can't be part of a note */
+                       goto handle_non_note;
                }
+
                if (note_tree_insert(t, node, n, l, type,
                                     combine_notes_concatenate))
                        die("Failed to load %s %s into notes tree "
@@ -468,23 +481,13 @@ static void load_subtree(struct notes_tree *t, struct leaf_node *subtree,
 
 handle_non_note:
                /*
-                * Determine full path for this non-note entry:
-                * The filename is already found in entry.path, but the
-                * directory part of the path must be deduced from the subtree
-                * containing this entry. We assume here that the overall notes
-                * tree follows a strict byte-based progressive fanout
-                * structure (i.e. using 2/38, 2/2/36, etc. fanouts, and not
-                * e.g. 4/36 fanout). This means that if a non-note is found at
-                * path "dead/beef", the following code will register it as
-                * being found on "de/ad/beef".
-                * On the other hand, if you use such non-obvious non-note
-                * paths in the middle of a notes tree, you deserve what's
-                * coming to you ;). Note that for non-notes that are not
-                * SHA1-like at the top level, there will be no problems.
-                *
-                * To conclude, it is strongly advised to make sure non-notes
-                * have at least one non-hex character in the top-level path
-                * component.
+                * Determine full path for this non-note entry. The
+                * filename is already found in entry.path, but the
+                * directory part of the path must be deduced from the
+                * subtree containing this entry based on our
+                * knowledge that the overall notes tree follows a
+                * strict byte-based progressive fanout structure
+                * (i.e. using 2/38, 2/2/36, etc. fanouts).
                 */
                {
                        struct strbuf non_note_path = STRBUF_INIT;