@ -1,5 +1,6 @@
@@ -1,5 +1,6 @@
#include "cache.h"
#include "notes.h"
#include "blob.h"
#include "tree.h"
#include "utf8.h"
#include "strbuf.h"
@ -127,55 +128,12 @@ static struct leaf_node *note_tree_find(struct int_node *tree, unsigned char n,
@@ -127,55 +128,12 @@ static struct leaf_node *note_tree_find(struct int_node *tree, unsigned char n,
return NULL;
}
/* Create a new blob object by concatenating the two given blob objects */
static int concatenate_notes(unsigned char *cur_sha1,
const unsigned char *new_sha1)
{
char *cur_msg, *new_msg, *buf;
unsigned long cur_len, new_len, buf_len;
enum object_type cur_type, new_type;
int ret;
/* read in both note blob objects */
new_msg = read_sha1_file(new_sha1, &new_type, &new_len);
if (!new_msg || !new_len || new_type != OBJ_BLOB) {
free(new_msg);
return 0;
}
cur_msg = read_sha1_file(cur_sha1, &cur_type, &cur_len);
if (!cur_msg || !cur_len || cur_type != OBJ_BLOB) {
free(cur_msg);
free(new_msg);
hashcpy(cur_sha1, new_sha1);
return 0;
}
/* we will separate the notes by a newline anyway */
if (cur_msg[cur_len - 1] == '\n')
cur_len--;
/* concatenate cur_msg and new_msg into buf */
buf_len = cur_len + 1 + new_len;
buf = (char *) xmalloc(buf_len);
memcpy(buf, cur_msg, cur_len);
buf[cur_len] = '\n';
memcpy(buf + cur_len + 1, new_msg, new_len);
free(cur_msg);
free(new_msg);
/* create a new blob object from buf */
ret = write_sha1_file(buf, buf_len, "blob", cur_sha1);
free(buf);
return ret;
}
/*
* To insert a leaf_node:
* Search to the tree location appropriate for the given leaf_node's key:
* - If location is unused (NULL), store the tweaked pointer directly there
* - If location holds a note entry that matches the note-to-be-inserted, then
* concatenate the two notes.
* combine the two notes (by calling the given combine_notes function).
* - If location holds a note entry that matches the subtree-to-be-inserted,
* then unpack the subtree-to-be-inserted into the location.
* - If location holds a matching subtree entry, unpack the subtree at that
@ -184,7 +142,8 @@ static int concatenate_notes(unsigned char *cur_sha1,
@@ -184,7 +142,8 @@ static int concatenate_notes(unsigned char *cur_sha1,
* node-to-be-inserted, and store the new int_node into the location.
*/
static void note_tree_insert(struct int_node *tree, unsigned char n,
struct leaf_node *entry, unsigned char type)
struct leaf_node *entry, unsigned char type,
combine_notes_fn combine_notes)
{
struct int_node *new_node;
struct leaf_node *l;
@ -205,12 +164,11 @@ static void note_tree_insert(struct int_node *tree, unsigned char n,
@@ -205,12 +164,11 @@ static void note_tree_insert(struct int_node *tree, unsigned char n,
if (!hashcmp(l->val_sha1, entry->val_sha1))
return;
if (concatenate_notes(l->val_sha1,
entry->val_sha1))
die("failed to concatenate note %s "
"into note %s for object %s",
sha1_to_hex(entry->val_sha1),
if (combine_notes(l->val_sha1, entry->val_sha1))
die("failed to combine notes %s and %s"
" for object %s",
sha1_to_hex(l->val_sha1),
sha1_to_hex(entry->val_sha1),
sha1_to_hex(l->key_sha1));
free(entry);
return;
@ -233,7 +191,7 @@ static void note_tree_insert(struct int_node *tree, unsigned char n,
@@ -233,7 +191,7 @@ static void note_tree_insert(struct int_node *tree, unsigned char n,
*p = NULL;
load_subtree(l, tree, n);
free(l);
note_tree_insert(tree, n, entry, type);
note_tree_insert(tree, n, entry, type, combine_notes);
return;
}
break;
@ -243,9 +201,9 @@ static void note_tree_insert(struct int_node *tree, unsigned char n,
@@ -243,9 +201,9 @@ static void note_tree_insert(struct int_node *tree, unsigned char n,
assert(GET_PTR_TYPE(*p) == PTR_TYPE_NOTE ||
GET_PTR_TYPE(*p) == PTR_TYPE_SUBTREE);
new_node = (struct int_node *) xcalloc(sizeof(struct int_node), 1);
note_tree_insert(new_node, n + 1, l, GET_PTR_TYPE(*p));
note_tree_insert(new_node, n + 1, l, GET_PTR_TYPE(*p), combine_notes);
*p = SET_PTR_TYPE(new_node, PTR_TYPE_INTERNAL);
note_tree_insert(new_node, n + 1, entry, type);
note_tree_insert(new_node, n + 1, entry, type, combine_notes);
}
/*
@ -406,7 +364,8 @@ static void load_subtree(struct leaf_node *subtree, struct int_node *node,
@@ -406,7 +364,8 @@ static void load_subtree(struct leaf_node *subtree, struct int_node *node,
l->key_sha1[19] = (unsigned char) len;
type = PTR_TYPE_SUBTREE;
}
note_tree_insert(node, n, l, type);
note_tree_insert(node, n, l, type,
combine_notes_concatenate);
}
}
free(buf);
@ -659,7 +618,64 @@ static int write_each_note(const unsigned char *object_sha1,
@@ -659,7 +618,64 @@ static int write_each_note(const unsigned char *object_sha1,
return write_each_note_helper(d->root, note_path, mode, note_sha1);
}
void init_notes(struct notes_tree *t, const char *notes_ref, int flags)
int combine_notes_concatenate(unsigned char *cur_sha1,
const unsigned char *new_sha1)
{
char *cur_msg = NULL, *new_msg = NULL, *buf;
unsigned long cur_len, new_len, buf_len;
enum object_type cur_type, new_type;
int ret;
/* read in both note blob objects */
if (!is_null_sha1(new_sha1))
new_msg = read_sha1_file(new_sha1, &new_type, &new_len);
if (!new_msg || !new_len || new_type != OBJ_BLOB) {
free(new_msg);
return 0;
}
if (!is_null_sha1(cur_sha1))
cur_msg = read_sha1_file(cur_sha1, &cur_type, &cur_len);
if (!cur_msg || !cur_len || cur_type != OBJ_BLOB) {
free(cur_msg);
free(new_msg);
hashcpy(cur_sha1, new_sha1);
return 0;
}
/* we will separate the notes by a newline anyway */
if (cur_msg[cur_len - 1] == '\n')
cur_len--;
/* concatenate cur_msg and new_msg into buf */
buf_len = cur_len + 1 + new_len;
buf = (char *) xmalloc(buf_len);
memcpy(buf, cur_msg, cur_len);
buf[cur_len] = '\n';
memcpy(buf + cur_len + 1, new_msg, new_len);
free(cur_msg);
free(new_msg);
/* create a new blob object from buf */
ret = write_sha1_file(buf, buf_len, blob_type, cur_sha1);
free(buf);
return ret;
}
int combine_notes_overwrite(unsigned char *cur_sha1,
const unsigned char *new_sha1)
{
hashcpy(cur_sha1, new_sha1);
return 0;
}
int combine_notes_ignore(unsigned char *cur_sha1,
const unsigned char *new_sha1)
{
return 0;
}
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];
unsigned mode;
@ -676,8 +692,12 @@ void init_notes(struct notes_tree *t, const char *notes_ref, int flags)
@@ -676,8 +692,12 @@ void init_notes(struct notes_tree *t, const char *notes_ref, int flags)
if (!notes_ref)
notes_ref = GIT_NOTES_DEFAULT_REF;
if (!combine_notes)
combine_notes = combine_notes_concatenate;
t->root = (struct int_node *) xcalloc(sizeof(struct int_node), 1);
t->ref = notes_ref ? xstrdup(notes_ref) : NULL;
t->combine_notes = combine_notes;
t->initialized = 1;
if (flags & NOTES_INIT_EMPTY || !notes_ref ||
@ -693,17 +713,19 @@ void init_notes(struct notes_tree *t, const char *notes_ref, int flags)
@@ -693,17 +713,19 @@ void init_notes(struct notes_tree *t, const char *notes_ref, int flags)
}
void add_note(struct notes_tree *t, const unsigned char *object_sha1,
const unsigned char *note_sha1)
const unsigned char *note_sha1, combine_notes_fn combine_notes)
{
struct leaf_node *l;
if (!t)
t = &default_notes_tree;
assert(t->initialized);
if (!combine_notes)
combine_notes = t->combine_notes;
l = (struct leaf_node *) xmalloc(sizeof(struct leaf_node));
hashcpy(l->key_sha1, object_sha1);
hashcpy(l->val_sha1, note_sha1);
note_tree_insert(t->root, 0, l, PTR_TYPE_NOTE);
note_tree_insert(t->root, 0, l, PTR_TYPE_NOTE, combine_notes);
}
void remove_note(struct notes_tree *t, const unsigned char *object_sha1)
@ -788,7 +810,7 @@ void format_note(struct notes_tree *t, const unsigned char *object_sha1,
@@ -788,7 +810,7 @@ void format_note(struct notes_tree *t, const unsigned char *object_sha1,
if (!t)
t = &default_notes_tree;
if (!t->initialized)
init_notes(t, NULL, 0);
init_notes(t, NULL, NULL, 0);
sha1 = get_note(t, object_sha1);
if (!sha1)