/* * Copyright (C) 2009-2012 the libgit2 contributors * * This file is part of libgit2, distributed under the GNU GPL v2 with * a Linking Exception. For full terms see the included COPYING file. */ #include "notes.h" #include "git2.h" #include "refs.h" #include "config.h" static int find_subtree(git_tree **subtree, const git_oid *root, git_repository *repo, const char *target, int *fanout) { int error; unsigned int i; git_tree *tree; const git_tree_entry *entry; *subtree = NULL; error = git_tree_lookup(&tree, repo, root); if (error < 0) return error; for (i=0; ioid, &oid); note->message = git__strdup(git_blob_rawcontent(blob)); GITERR_CHECK_ALLOC(note->message); *out = note; git_blob_free(blob); return error; } static int note_remove(git_repository *repo, git_signature *author, git_signature *committer, const char *notes_ref, const git_oid *tree_sha, const char *target, int nparents, git_commit **parents) { int error, fanout = 0; git_oid oid; git_tree *tree; git_treebuilder *tb; error = find_subtree(&tree, tree_sha, repo, target, &fanout); if (error < 0) return error; error = find_blob(&oid, tree, target + fanout); if (!error) error = git_treebuilder_create(&tb, tree); git_tree_free(tree); if (error < 0) return error; error = git_treebuilder_remove(tb, target + fanout); if (!error) error = git_treebuilder_write(&oid, repo, tb); git_treebuilder_free(tb); if (error < 0) return error; /* create new notes commit */ error = git_tree_lookup(&tree, repo, &oid); if (error < 0) return error; error = git_commit_create(&oid, repo, notes_ref, author, committer, NULL, GIT_NOTES_DEFAULT_MSG_RM, tree, nparents, (const git_commit **) parents); git_tree_free(tree); return error; } static int note_get_default_ref(const char **out, git_repository *repo) { int error; git_config *cfg; *out = NULL; if (git_repository_config__weakptr(&cfg, repo) < 0) return -1; error = git_config_get_string(cfg, "core.notesRef", out); if (error == GIT_ENOTFOUND) { *out = GIT_NOTES_DEFAULT_REF; return 0; } return error; } int git_note_read(git_note **out, git_repository *repo, const char *notes_ref, const git_oid *oid) { int error; char *target; git_reference *ref; git_commit *commit; const git_oid *sha; *out = NULL; if (!notes_ref) { error = note_get_default_ref(¬es_ref, repo); if (error < 0) return error; } error = git_reference_lookup(&ref, repo, notes_ref); if (error < 0) return error; assert(git_reference_type(ref) == GIT_REF_OID); sha = git_reference_oid(ref); error = git_commit_lookup(&commit, repo, sha); git_reference_free(ref); if (error < 0) return error; sha = git_commit_tree_oid(commit); git_commit_free(commit); target = git_oid_allocfmt(oid); GITERR_CHECK_ALLOC(target); error = note_lookup(out, repo, sha, target); git__free(target); return error; } int git_note_create( git_oid *out, git_repository *repo, git_signature *author, git_signature *committer, const char *notes_ref, const git_oid *oid, const char *note) { int error, nparents = 0; char *target; git_oid sha; git_commit *commit = NULL; git_reference *ref; if (!notes_ref) { error = note_get_default_ref(¬es_ref, repo); if (error < 0) return error; } error = git_reference_lookup(&ref, repo, notes_ref); if (error < 0 && error != GIT_ENOTFOUND) return error; if (!error) { assert(git_reference_type(ref) == GIT_REF_OID); /* lookup existing notes tree oid */ git_oid_cpy(&sha, git_reference_oid(ref)); git_reference_free(ref); error = git_commit_lookup(&commit, repo, &sha); if (error < 0) return error; git_oid_cpy(&sha, git_commit_tree_oid(commit)); nparents++; } target = git_oid_allocfmt(oid); GITERR_CHECK_ALLOC(target); error = note_write(out, repo, author, committer, notes_ref, note, nparents ? &sha : NULL, target, nparents, &commit); git__free(target); git_commit_free(commit); return error; } int git_note_remove(git_repository *repo, const char *notes_ref, git_signature *author, git_signature *committer, const git_oid *oid) { int error; char *target; git_oid sha; git_commit *commit; git_reference *ref; if (!notes_ref) { error = note_get_default_ref(¬es_ref, repo); if (error < 0) return error; } error = git_reference_lookup(&ref, repo, notes_ref); if (error < 0) return error; assert(git_reference_type(ref) == GIT_REF_OID); git_oid_cpy(&sha, git_reference_oid(ref)); git_reference_free(ref); error = git_commit_lookup(&commit, repo, &sha); if (error < 0) return error; git_oid_cpy(&sha, git_commit_tree_oid(commit)); target = git_oid_allocfmt(oid); GITERR_CHECK_ALLOC(target); error = note_remove(repo, author, committer, notes_ref, &sha, target, 1, &commit); git__free(target); git_commit_free(commit); return error; } int git_note_default_ref(const char **out, git_repository *repo) { assert(repo); return note_get_default_ref(out, repo); } const char * git_note_message(git_note *note) { assert(note); return note->message; } const git_oid * git_note_oid(git_note *note) { assert(note); return ¬e->oid; } void git_note_free(git_note *note) { if (note == NULL) return; git__free(note->message); git__free(note); }