Merge branch 'rp/p4-filetype-change'
[gitweb.git] / notes.c
diff --git a/notes.c b/notes.c
index df08209dee498d624817f071d7e9ac5194d2334f..358e2fdb74eb8cc92f16b33891a9a5f0a508de9c 100644 (file)
--- a/notes.c
+++ b/notes.c
@@ -362,13 +362,14 @@ static int non_note_cmp(const struct non_note *a, const struct non_note *b)
        return strcmp(a->path, b->path);
 }
 
-static void add_non_note(struct notes_tree *t, const char *path,
+/* note: takes ownership of path string */
+static void add_non_note(struct notes_tree *t, char *path,
                unsigned int mode, const unsigned char *sha1)
 {
        struct non_note *p = t->prev_non_note, *n;
        n = (struct non_note *) xmalloc(sizeof(struct non_note));
        n->next = NULL;
-       n->path = xstrdup(path);
+       n->path = path;
        n->mode = mode;
        hashcpy(n->sha1, sha1);
        t->prev_non_note = n;
@@ -482,17 +483,17 @@ static void load_subtree(struct notes_tree *t, struct leaf_node *subtree,
                 * component.
                 */
                {
-                       char non_note_path[PATH_MAX];
-                       char *p = non_note_path;
+                       struct strbuf non_note_path = STRBUF_INIT;
                        const char *q = sha1_to_hex(subtree->key_sha1);
                        int i;
                        for (i = 0; i < prefix_len; i++) {
-                               *p++ = *q++;
-                               *p++ = *q++;
-                               *p++ = '/';
+                               strbuf_addch(&non_note_path, *q++);
+                               strbuf_addch(&non_note_path, *q++);
+                               strbuf_addch(&non_note_path, '/');
                        }
-                       strcpy(p, entry.path);
-                       add_non_note(t, non_note_path, entry.mode, entry.sha1);
+                       strbuf_addstr(&non_note_path, entry.path);
+                       add_non_note(t, strbuf_detach(&non_note_path, NULL),
+                                    entry.mode, entry.sha1);
                }
        }
        free(buf);
@@ -538,6 +539,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)
 {
@@ -550,7 +554,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,
@@ -561,7 +565,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++) {
@@ -594,7 +598,7 @@ static int for_each_note_helper(struct notes_tree *t, struct int_node *tree,
                                /* 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 */
@@ -1007,13 +1011,16 @@ 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_sha1))
                return;
+       if (flags & NOTES_INIT_WRITABLE && read_ref(notes_ref, object_sha1))
+               die("Cannot use notes ref %s", notes_ref);
        if (get_tree_entry(object_sha1, "", sha1, &mode))
                die("Failed to read notes tree referenced by %s (%s)",
                    notes_ref, sha1_to_hex(object_sha1));
@@ -1023,7 +1030,7 @@ void init_notes(struct notes_tree *t, const char *notes_ref,
        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;
@@ -1031,7 +1038,7 @@ struct notes_tree **load_notes_trees(struct string_list *refs)
        trees = xmalloc((refs->nr+1) * sizeof(struct notes_tree *));
        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;
@@ -1067,7 +1074,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);
 }