Imported Upstream version 2.13.0
[platform/upstream/git.git] / notes.c
diff --git a/notes.c b/notes.c
index d465200..542563b 100644 (file)
--- a/notes.c
+++ b/notes.c
@@ -70,7 +70,7 @@ struct non_note {
 
 struct notes_tree default_notes_tree;
 
-static struct string_list display_notes_refs;
+static struct string_list display_notes_refs = STRING_LIST_INIT_NODUP;
 static struct notes_tree **display_notes_trees;
 
 static void load_subtree(struct notes_tree *t, struct leaf_node *subtree,
@@ -153,8 +153,8 @@ static struct leaf_node *note_tree_find(struct notes_tree *t,
  * How to consolidate an int_node:
  * If there are > 1 non-NULL entries, give up and return non-zero.
  * Otherwise replace the int_node at the given index in the given parent node
- * with the only entry (or a NULL entry if no entries) from the given tree,
- * and return 0.
+ * with the only NOTE entry (or a NULL entry if no entries) from the given
+ * tree, and return 0.
  */
 static int note_tree_consolidate(struct int_node *tree,
        struct int_node *parent, unsigned char index)
@@ -173,6 +173,8 @@ static int note_tree_consolidate(struct int_node *tree,
                }
        }
 
+       if (p && (GET_PTR_TYPE(p) != PTR_TYPE_NOTE))
+               return -2;
        /* replace tree with p in parent[index] */
        parent->a[index] = p;
        free(tree);
@@ -446,7 +448,7 @@ static void load_subtree(struct notes_tree *t, struct leaf_node *subtree,
                        l = (struct leaf_node *)
                                xcalloc(1, sizeof(struct leaf_node));
                        hashcpy(l->key_sha1, object_sha1);
-                       hashcpy(l->val_sha1, entry.sha1);
+                       hashcpy(l->val_sha1, entry.oid->hash);
                        if (len < 20) {
                                if (!S_ISDIR(entry.mode) || path_len != 2)
                                        goto handle_non_note; /* not subtree */
@@ -493,7 +495,7 @@ handle_non_note:
                        }
                        strbuf_addstr(&non_note_path, entry.path);
                        add_non_note(t, strbuf_detach(&non_note_path, NULL),
-                                    entry.mode, entry.sha1);
+                                    entry.mode, entry.oid->hash);
                }
        }
        free(buf);
@@ -539,6 +541,9 @@ static unsigned char determine_fanout(struct int_node *tree, unsigned char n,
        return fanout + 1;
 }
 
+/* hex SHA1 + 19 * '/' + NUL */
+#define FANOUT_PATH_MAX 40 + 19 + 1
+
 static void construct_path_with_fanout(const unsigned char *sha1,
                unsigned char fanout, char *path)
 {
@@ -551,7 +556,7 @@ static void construct_path_with_fanout(const unsigned char *sha1,
                path[i++] = '/';
                fanout--;
        }
-       strcpy(path + i, hex_sha1 + j);
+       xsnprintf(path + i, FANOUT_PATH_MAX - i, "%s", hex_sha1 + j);
 }
 
 static int for_each_note_helper(struct notes_tree *t, struct int_node *tree,
@@ -562,7 +567,7 @@ static int for_each_note_helper(struct notes_tree *t, struct int_node *tree,
        void *p;
        int ret = 0;
        struct leaf_node *l;
-       static char path[40 + 19 + 1];  /* hex SHA1 + 19 * '/' + NUL */
+       static char path[FANOUT_PATH_MAX];
 
        fanout = determine_fanout(tree, n, fanout);
        for (i = 0; i < 16; i++) {
@@ -595,7 +600,7 @@ redo:
                                /* invoke callback with subtree */
                                unsigned int path_len =
                                        l->key_sha1[19] * 2 + fanout;
-                               assert(path_len < 40 + 19);
+                               assert(path_len < FANOUT_PATH_MAX - 1);
                                construct_path_with_fanout(l->key_sha1, fanout,
                                                           path);
                                /* Create trailing slash, if needed */
@@ -919,7 +924,7 @@ out:
        return ret;
 }
 
-static int string_list_add_one_ref(const char *refname, const unsigned char *sha1,
+static int string_list_add_one_ref(const char *refname, const struct object_id *oid,
                                   int flag, void *cb)
 {
        struct string_list *refs = cb;
@@ -990,7 +995,7 @@ const char *default_notes_ref(void)
 void init_notes(struct notes_tree *t, const char *notes_ref,
                combine_notes_fn combine_notes, int flags)
 {
-       unsigned char sha1[20], object_sha1[20];
+       struct object_id oid, object_oid;
        unsigned mode;
        struct leaf_node root_tree;
 
@@ -1008,31 +1013,34 @@ void init_notes(struct notes_tree *t, const char *notes_ref,
        t->first_non_note = NULL;
        t->prev_non_note = NULL;
        t->ref = xstrdup_or_null(notes_ref);
+       t->update_ref = (flags & NOTES_INIT_WRITABLE) ? t->ref : NULL;
        t->combine_notes = combine_notes;
        t->initialized = 1;
        t->dirty = 0;
 
        if (flags & NOTES_INIT_EMPTY || !notes_ref ||
-           read_ref(notes_ref, object_sha1))
+           get_sha1_treeish(notes_ref, object_oid.hash))
                return;
-       if (get_tree_entry(object_sha1, "", sha1, &mode))
+       if (flags & NOTES_INIT_WRITABLE && read_ref(notes_ref, object_oid.hash))
+               die("Cannot use notes ref %s", notes_ref);
+       if (get_tree_entry(object_oid.hash, "", oid.hash, &mode))
                die("Failed to read notes tree referenced by %s (%s)",
-                   notes_ref, sha1_to_hex(object_sha1));
+                   notes_ref, oid_to_hex(&object_oid));
 
        hashclr(root_tree.key_sha1);
-       hashcpy(root_tree.val_sha1, sha1);
+       hashcpy(root_tree.val_sha1, oid.hash);
        load_subtree(t, &root_tree, t->root, 0);
 }
 
-struct notes_tree **load_notes_trees(struct string_list *refs)
+struct notes_tree **load_notes_trees(struct string_list *refs, int flags)
 {
        struct string_list_item *item;
        int counter = 0;
        struct notes_tree **trees;
-       trees = xmalloc((refs->nr+1) * sizeof(struct notes_tree *));
+       ALLOC_ARRAY(trees, refs->nr + 1);
        for_each_string_list_item(item, refs) {
                struct notes_tree *t = xcalloc(1, sizeof(struct notes_tree));
-               init_notes(t, item->string, combine_notes_ignore, 0);
+               init_notes(t, item->string, combine_notes_ignore, flags);
                trees[counter++] = t;
        }
        trees[counter] = NULL;
@@ -1068,7 +1076,7 @@ void init_display_notes(struct display_notes_opt *opt)
                                                     item->string);
        }
 
-       display_notes_trees = load_notes_trees(&display_notes_refs);
+       display_notes_trees = load_notes_trees(&display_notes_refs, 0);
        string_list_clear(&display_notes_refs, 0);
 }
 
@@ -1300,3 +1308,13 @@ void expand_notes_ref(struct strbuf *sb)
        else
                strbuf_insert(sb, 0, "refs/notes/", 11);
 }
+
+void expand_loose_notes_ref(struct strbuf *sb)
+{
+       unsigned char object[20];
+
+       if (get_sha1(sb->buf, object)) {
+               /* fallback to expand_notes_ref */
+               expand_notes_ref(sb);
+       }
+}