1
0
mirror of https://github.com/git/git.git synced 2024-11-18 19:03:52 +01:00
git/notes-cache.c
Mike Hommey ee76f92fe8 notes: allow treeish expressions as notes ref
init_notes() is the main point of entry to the notes API. It ensures
that the input can be used as ref, because it needs a ref to update to
store notes tree after modifying it.

There however are many use cases where notes tree is only read, e.g.
"git log --notes=...".  Any notes-shaped treeish could be used for such
purpose, but it is not allowed due to existing restriction.

Allow treeish expressions to be used in the case the notes tree is going
to be used without write "permissions".  Add a flag to distinguish
whether the notes tree is intended to be used read-only, or will be
updated.

With this change, operations that use notes read-only can be fed any
notes-shaped tree-ish can be used, e.g. git log --notes=notes@{1}.

Signed-off-by: Mike Hommey <mh@glandium.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-01-12 15:10:01 -08:00

96 lines
2.2 KiB
C

#include "cache.h"
#include "notes-cache.h"
#include "commit.h"
#include "refs.h"
static int notes_cache_match_validity(const char *ref, const char *validity)
{
unsigned char sha1[20];
struct commit *commit;
struct pretty_print_context pretty_ctx;
struct strbuf msg = STRBUF_INIT;
int ret;
if (read_ref(ref, sha1) < 0)
return 0;
commit = lookup_commit_reference_gently(sha1, 1);
if (!commit)
return 0;
memset(&pretty_ctx, 0, sizeof(pretty_ctx));
format_commit_message(commit, "%s", &msg, &pretty_ctx);
strbuf_trim(&msg);
ret = !strcmp(msg.buf, validity);
strbuf_release(&msg);
return ret;
}
void notes_cache_init(struct notes_cache *c, const char *name,
const char *validity)
{
struct strbuf ref = STRBUF_INIT;
int flags = NOTES_INIT_WRITABLE;
memset(c, 0, sizeof(*c));
c->validity = xstrdup(validity);
strbuf_addf(&ref, "refs/notes/%s", name);
if (!notes_cache_match_validity(ref.buf, validity))
flags |= NOTES_INIT_EMPTY;
init_notes(&c->tree, ref.buf, combine_notes_overwrite, flags);
strbuf_release(&ref);
}
int notes_cache_write(struct notes_cache *c)
{
unsigned char tree_sha1[20];
unsigned char commit_sha1[20];
if (!c || !c->tree.initialized || !c->tree.update_ref ||
!*c->tree.update_ref)
return -1;
if (!c->tree.dirty)
return 0;
if (write_notes_tree(&c->tree, tree_sha1))
return -1;
if (commit_tree(c->validity, strlen(c->validity), tree_sha1, NULL,
commit_sha1, NULL, NULL) < 0)
return -1;
if (update_ref("update notes cache", c->tree.update_ref, commit_sha1,
NULL, 0, UPDATE_REFS_QUIET_ON_ERR) < 0)
return -1;
return 0;
}
char *notes_cache_get(struct notes_cache *c, unsigned char key_sha1[20],
size_t *outsize)
{
const unsigned char *value_sha1;
enum object_type type;
char *value;
unsigned long size;
value_sha1 = get_note(&c->tree, key_sha1);
if (!value_sha1)
return NULL;
value = read_sha1_file(value_sha1, &type, &size);
*outsize = size;
return value;
}
int notes_cache_put(struct notes_cache *c, unsigned char key_sha1[20],
const char *data, size_t size)
{
unsigned char value_sha1[20];
if (write_sha1_file(data, size, "blob", value_sha1) < 0)
return -1;
return add_note(&c->tree, key_sha1, value_sha1, NULL);
}