notes.c 17 KB
Newer Older
schu committed
1
/*
Edward Thomson committed
2
 * Copyright (C) the libgit2 contributors. All rights reserved.
schu committed
3 4 5 6 7 8 9 10 11
 *
 * 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"
12
#include "config.h"
13
#include "iterator.h"
Ben Straub committed
14
#include "signature.h"
15
#include "blob.h"
schu committed
16

17 18
static int note_error_notfound(void)
{
19
	git_error_set(GIT_ERROR_INVALID, "note could not be found");
20 21 22
	return GIT_ENOTFOUND;
}

23 24 25 26 27 28
static int find_subtree_in_current_level(
	git_tree **out,
	git_repository *repo,
	git_tree *parent,
	const char *annotated_object_sha,
	int fanout)
schu committed
29
{
30
	size_t i;
schu committed
31 32
	const git_tree_entry *entry;

33
	*out = NULL;
34

35
	if (parent == NULL)
36
		return note_error_notfound();
schu committed
37

38 39
	for (i = 0; i < git_tree_entrycount(parent); i++) {
		entry = git_tree_entry_byindex(parent, i);
schu committed
40 41 42 43

		if (!git__ishex(git_tree_entry_name(entry)))
			continue;

44
		if (S_ISDIR(git_tree_entry_filemode(entry))
45
			&& strlen(git_tree_entry_name(entry)) == 2
46 47
			&& !strncmp(git_tree_entry_name(entry), annotated_object_sha + fanout, 2))
			return git_tree_lookup(out, repo, git_tree_entry_id(entry));
schu committed
48

49
		/* Not a DIR, so do we have an already existing blob? */
50
		if (!strcmp(git_tree_entry_name(entry), annotated_object_sha + fanout))
51 52
			return GIT_EEXISTS;
	}
schu committed
53

54
	return note_error_notfound();
55
}
schu committed
56

57 58 59 60 61
static int find_subtree_r(git_tree **out, git_tree *root,
			git_repository *repo, const char *target, int *fanout)
{
	int error;
	git_tree *subtree = NULL;
schu committed
62

63
	*out = NULL;
schu committed
64

65
	error = find_subtree_in_current_level(&subtree, repo, root, target, *fanout);
66
	if (error == GIT_EEXISTS)
67
		return git_tree_lookup(out, repo, git_tree_id(root));
schu committed
68

69
	if (error < 0)
70
		return error;
71 72 73

	*fanout += 2;
	error = find_subtree_r(out, subtree, repo, target, fanout);
74
	git_tree_free(subtree);
75 76

	return error;
schu committed
77 78 79 80
}

static int find_blob(git_oid *blob, git_tree *tree, const char *target)
{
81
	size_t i;
schu committed
82 83 84 85 86 87 88 89 90
	const git_tree_entry *entry;

	for (i=0; i<git_tree_entrycount(tree); i++) {
		entry = git_tree_entry_byindex(tree, i);

		if (!strcmp(git_tree_entry_name(entry), target)) {
			/* found matching note object - return */

			git_oid_cpy(blob, git_tree_entry_id(entry));
91
			return 0;
schu committed
92 93
		}
	}
94 95

	return note_error_notfound();
schu committed
96 97
}

98 99 100 101 102 103 104
static int tree_write(
	git_tree **out,
	git_repository *repo,
	git_tree *source_tree,
	const git_oid *object_oid,
	const char *treeentry_name,
	unsigned int attributes)
schu committed
105
{
106 107
	int error;
	git_treebuilder *tb = NULL;
108
	const git_tree_entry *entry;
109
	git_oid tree_oid;
schu committed
110

111
	if ((error = git_treebuilder_new(&tb, repo, source_tree)) < 0)
112
		goto cleanup;
schu committed
113

114
	if (object_oid) {
115 116
		if ((error = git_treebuilder_insert(
				&entry, tb, treeentry_name, object_oid, attributes)) < 0)
117 118 119 120 121
			goto cleanup;
	} else {
		if ((error = git_treebuilder_remove(tb, treeentry_name)) < 0)
			goto cleanup;
	}
schu committed
122

123
	if ((error = git_treebuilder_write(&tree_oid, tb)) < 0)
124
		goto cleanup;
schu committed
125

126
	error = git_tree_lookup(out, repo, &tree_oid);
schu committed
127

128 129 130 131
cleanup:
	git_treebuilder_free(tb);
	return error;
}
schu committed
132

133 134 135 136 137 138
static int manipulate_note_in_tree_r(
	git_tree **out,
	git_repository *repo,
	git_tree *parent,
	git_oid *note_oid,
	const char *annotated_object_sha,
139
	int fanout,
140
	int (*note_exists_cb)(
141 142
		git_tree **out,
		git_repository *repo,
143 144 145 146 147 148 149 150 151 152 153 154 155
		git_tree *parent,
		git_oid *note_oid,
		const char *annotated_object_sha,
		int fanout,
		int current_error),
	int (*note_notfound_cb)(
		git_tree **out,
		git_repository *repo,
		git_tree *parent,
		git_oid *note_oid,
		const char *annotated_object_sha,
		int fanout,
		int current_error))
156
{
157
	int error;
158
	git_tree *subtree = NULL, *new = NULL;
159
	char subtree_name[3];
schu committed
160

161 162
	error = find_subtree_in_current_level(
		&subtree, repo, parent, annotated_object_sha, fanout);
schu committed
163

164
	if (error == GIT_EEXISTS) {
165 166
		error = note_exists_cb(
			out, repo, parent, note_oid, annotated_object_sha, fanout, error);
167 168
		goto cleanup;
	}
schu committed
169

170
	if (error == GIT_ENOTFOUND) {
171 172
		error = note_notfound_cb(
			out, repo, parent, note_oid, annotated_object_sha, fanout, error);
173 174
		goto cleanup;
	}
schu committed
175

176
	if (error < 0)
177
		goto cleanup;
schu committed
178

179
	/* An existing fanout has been found, let's dig deeper */
180
	error = manipulate_note_in_tree_r(
181
		&new, repo, subtree, note_oid, annotated_object_sha,
182
		fanout + 2, note_exists_cb, note_notfound_cb);
schu committed
183

184 185
	if (error < 0)
		goto cleanup;
schu committed
186

187 188
	strncpy(subtree_name, annotated_object_sha + fanout, 2);
	subtree_name[2] = '\0';
schu committed
189

190
	error = tree_write(out, repo, parent, git_tree_id(new),
nulltoken committed
191
			   subtree_name, GIT_FILEMODE_TREE);
192

193

194
cleanup:
195
	git_tree_free(new);
196 197 198
	git_tree_free(subtree);
	return error;
}
schu committed
199

200 201 202 203 204 205 206 207 208
static int remove_note_in_tree_eexists_cb(
	git_tree **out,
	git_repository *repo,
	git_tree *parent,
	git_oid *note_oid,
	const char *annotated_object_sha,
	int fanout,
	int current_error)
{
209 210
	GIT_UNUSED(note_oid);
	GIT_UNUSED(current_error);
schu committed
211

212 213
	return tree_write(out, repo, parent, NULL, annotated_object_sha + fanout, 0);
}
schu committed
214

215 216 217 218 219 220 221 222 223
static int remove_note_in_tree_enotfound_cb(
	git_tree **out,
	git_repository *repo,
	git_tree *parent,
	git_oid *note_oid,
	const char *annotated_object_sha,
	int fanout,
	int current_error)
{
224 225 226 227 228
	GIT_UNUSED(out);
	GIT_UNUSED(repo);
	GIT_UNUSED(parent);
	GIT_UNUSED(note_oid);
	GIT_UNUSED(fanout);
schu committed
229

230
	git_error_set(GIT_ERROR_REPOSITORY, "object '%s' has no note", annotated_object_sha);
231 232
	return current_error;
}
schu committed
233

234 235 236 237 238 239 240 241
static int insert_note_in_tree_eexists_cb(git_tree **out,
	git_repository *repo,
	git_tree *parent,
	git_oid *note_oid,
	const char *annotated_object_sha,
	int fanout,
	int current_error)
{
242 243 244 245 246
	GIT_UNUSED(out);
	GIT_UNUSED(repo);
	GIT_UNUSED(parent);
	GIT_UNUSED(note_oid);
	GIT_UNUSED(fanout);
schu committed
247

248
	git_error_set(GIT_ERROR_REPOSITORY, "note for '%s' exists already", annotated_object_sha);
249 250
	return current_error;
}
schu committed
251

252 253 254 255 256 257 258 259
static int insert_note_in_tree_enotfound_cb(git_tree **out,
	git_repository *repo,
	git_tree *parent,
	git_oid *note_oid,
	const char *annotated_object_sha,
	int fanout,
	int current_error)
{
260
	GIT_UNUSED(current_error);
schu committed
261

262
	/* No existing fanout at this level, insert in place */
nulltoken committed
263 264 265 266 267 268 269
	return tree_write(
		out,
		repo,
		parent,
		note_oid,
		annotated_object_sha + fanout,
		GIT_FILEMODE_BLOB);
schu committed
270 271
}

272 273 274
static int note_write(
	git_oid *notes_commit_out,
	git_oid *notes_blob_out,
275
	git_repository *repo,
Ben Straub committed
276 277
	const git_signature *author,
	const git_signature *committer,
278 279 280 281
	const char *notes_ref,
	const char *note,
	git_tree *commit_tree,
	const char *target,
282 283
	git_commit **parents,
	int allow_note_overwrite)
schu committed
284
{
285
	int error;
schu committed
286
	git_oid oid;
287
	git_tree *tree = NULL;
288

289
	/* TODO: should we apply filters? */
290
	/* create note object */
291
	if ((error = git_blob_create_from_buffer(&oid, repo, note, strlen(note))) < 0)
292
		goto cleanup;
schu committed
293

294 295
	if ((error = manipulate_note_in_tree_r(
		&tree, repo, commit_tree, &oid, target, 0,
296 297
		allow_note_overwrite ? insert_note_in_tree_enotfound_cb : insert_note_in_tree_eexists_cb,
		insert_note_in_tree_enotfound_cb)) < 0)
298
		goto cleanup;
schu committed
299

300 301 302
	if (notes_blob_out)
		git_oid_cpy(notes_blob_out, &oid);

303

304 305 306
	error = git_commit_create(&oid, repo, notes_ref, author, committer,
				  NULL, GIT_NOTES_DEFAULT_MSG_ADD,
				  tree, *parents == NULL ? 0 : 1, (const git_commit **) parents);
307

308 309 310
	if (notes_commit_out)
		git_oid_cpy(notes_commit_out, &oid);

311
cleanup:
schu committed
312
	git_tree_free(tree);
313 314
	return error;
}
schu committed
315

316 317 318 319 320
static int note_new(
	git_note **out,
	git_oid *note_oid,
	git_commit *commit,
	git_blob *blob)
321 322
{
	git_note *note = NULL;
323
	git_object_size_t blobsize;
schu committed
324

325
	note = git__malloc(sizeof(git_note));
326
	GIT_ERROR_CHECK_ALLOC(note);
schu committed
327

328
	git_oid_cpy(&note->id, note_oid);
329 330 331 332 333

	if (git_signature_dup(&note->author, git_commit_author(commit)) < 0 ||
		git_signature_dup(&note->committer, git_commit_committer(commit)) < 0)
		return -1;

334 335 336 337
	blobsize = git_blob_rawsize(blob);
	GIT_ERROR_CHECK_BLOBSIZE(blobsize);

	note->message = git__strndup(git_blob_rawcontent(blob), (size_t)blobsize);
338
	GIT_ERROR_CHECK_ALLOC(note->message);
schu committed
339 340

	*out = note;
341
	return 0;
schu committed
342 343
}

344
static int note_lookup(
345 346 347 348 349
	git_note **out,
	git_repository *repo,
	git_commit *commit,
	git_tree *tree,
	const char *target)
schu committed
350 351 352
{
	int error, fanout = 0;
	git_oid oid;
353 354 355
	git_blob *blob = NULL;
	git_note *note = NULL;
	git_tree *subtree = NULL;
schu committed
356

357 358
	if ((error = find_subtree_r(&subtree, tree, repo, target, &fanout)) < 0)
		goto cleanup;
schu committed
359

360 361
	if ((error = find_blob(&oid, subtree, target + fanout)) < 0)
		goto cleanup;
schu committed
362

363 364
	if ((error = git_blob_lookup(&blob, repo, &oid)) < 0)
		goto cleanup;
schu committed
365

366
	if ((error = note_new(&note, &oid, commit, blob)) < 0)
367
		goto cleanup;
schu committed
368

369
	*out = note;
schu committed
370

371 372 373 374 375
cleanup:
	git_tree_free(subtree);
	git_blob_free(blob);
	return error;
}
schu committed
376

377 378 379
static int note_remove(
		git_oid *notes_commit_out,
		git_repository *repo,
Ben Straub committed
380 381 382
		const git_signature *author, const git_signature *committer,
		const char *notes_ref, git_tree *tree,
		const char *target, git_commit **parents)
383 384 385 386
{
	int error;
	git_tree *tree_after_removal = NULL;
	git_oid oid;
387

388 389 390
	if ((error = manipulate_note_in_tree_r(
		&tree_after_removal, repo, tree, NULL, target, 0,
		remove_note_in_tree_eexists_cb, remove_note_in_tree_enotfound_cb)) < 0)
391
		goto cleanup;
schu committed
392 393

	error = git_commit_create(&oid, repo, notes_ref, author, committer,
394 395 396 397
	  NULL, GIT_NOTES_DEFAULT_MSG_RM,
	  tree_after_removal,
	  *parents == NULL ? 0 : 1,
	  (const git_commit **) parents);
schu committed
398

399 400 401 402 403 404
	if (error < 0)
		goto cleanup;

	if (notes_commit_out)
		git_oid_cpy(notes_commit_out, &oid);

405 406
cleanup:
	git_tree_free(tree_after_removal);
schu committed
407 408 409
	return error;
}

410
static int note_get_default_ref(char **out, git_repository *repo)
411 412
{
	git_config *cfg;
413
	int ret = git_repository_config__weakptr(&cfg, repo);
414

415 416
	*out = (ret != 0) ? NULL : git_config__get_string_force(
		cfg, "core.notesref", GIT_NOTES_DEFAULT_REF);
417

418
	return ret;
419 420
}

421
static int normalize_namespace(char **out, git_repository *repo, const char *notes_ref)
422
{
423 424
	if (notes_ref) {
		*out = git__strdup(notes_ref);
425
		GIT_ERROR_CHECK_ALLOC(*out);
426
		return 0;
427
	}
428

429
	return note_get_default_ref(out, repo);
430 431
}

432
static int retrieve_note_commit(
433
	git_commit **commit_out,
434
	char **notes_ref_out,
435
	git_repository *repo,
436
	const char *notes_ref)
437
{
438
	int error;
439 440
	git_oid oid;

441
	if ((error = normalize_namespace(notes_ref_out, repo, notes_ref)) < 0)
442
		return error;
443

444
	if ((error = git_reference_name_to_id(&oid, repo, *notes_ref_out)) < 0)
445
		return error;
446

447 448
	if (git_commit_lookup(commit_out, repo, &oid) < 0)
		return error;
449

450
	return 0;
451 452
}

453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474
int git_note_commit_read(
	git_note **out,
	git_repository *repo,
	git_commit *notes_commit,
	const git_oid *oid)
{
	int error;
	git_tree *tree = NULL;
	char target[GIT_OID_HEXSZ + 1];

	git_oid_tostr(target, sizeof(target), oid);

	if ((error = git_commit_tree(&tree, notes_commit)) < 0)
		goto cleanup;

	error = note_lookup(out, repo, notes_commit, tree, target);

cleanup:
	git_tree_free(tree);
	return error;
}

475 476
int git_note_read(git_note **out, git_repository *repo,
		  const char *notes_ref_in, const git_oid *oid)
schu committed
477
{
478
	int error;
479
	char *notes_ref = NULL;
schu committed
480 481
	git_commit *commit = NULL;

482
	error = retrieve_note_commit(&commit, &notes_ref, repo, notes_ref_in);
schu committed
483

484
	if (error < 0)
485 486
		goto cleanup;

487
	error = git_note_commit_read(out, repo, commit, oid);
schu committed
488

489
cleanup:
490
	git__free(notes_ref);
schu committed
491
	git_commit_free(commit);
492
	return error;
schu committed
493 494
}

495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525
int git_note_commit_create(
	git_oid *notes_commit_out,
	git_oid *notes_blob_out,
	git_repository *repo,
	git_commit *parent,
	const git_signature *author,
	const git_signature *committer,
	const git_oid *oid,
	const char *note,
	int allow_note_overwrite)
{
	int error;
	git_tree *tree = NULL;
	char target[GIT_OID_HEXSZ + 1];

	git_oid_tostr(target, sizeof(target), oid);

	if (parent != NULL && (error = git_commit_tree(&tree, parent)) < 0)
		goto cleanup;

	error = note_write(notes_commit_out, notes_blob_out, repo, author,
			committer, NULL, note, tree, target, &parent, allow_note_overwrite);

	if (error < 0)
		goto cleanup;

cleanup:
	git_tree_free(tree);
	return error;
}

526 527 528 529 530 531 532 533 534
int git_note_create(
	git_oid *out,
	git_repository *repo,
	const char *notes_ref_in,
	const git_signature *author,
	const git_signature *committer,
	const git_oid *oid,
	const char *note,
	int allow_note_overwrite)
schu committed
535 536
{
	int error;
537 538 539 540
	char *notes_ref = NULL;
	git_commit *existing_notes_commit = NULL;
	git_reference *ref = NULL;
	git_oid notes_blob_oid, notes_commit_oid;
schu committed
541

542 543 544 545 546 547 548 549 550 551 552 553 554
	error = retrieve_note_commit(&existing_notes_commit, &notes_ref,
			repo, notes_ref_in);

	if (error < 0 && error != GIT_ENOTFOUND)
		goto cleanup;

	error = git_note_commit_create(&notes_commit_oid,
			&notes_blob_oid,
			repo, existing_notes_commit, author,
			committer, oid, note,
			allow_note_overwrite);
	if (error < 0)
		goto cleanup;
schu committed
555

556 557
	error = git_reference_create(&ref, repo, notes_ref,
				&notes_commit_oid, 1, NULL);
schu committed
558

559 560 561 562
	if (out != NULL)
		git_oid_cpy(out, &notes_blob_oid);

cleanup:
563
	git__free(notes_ref);
564 565
	git_commit_free(existing_notes_commit);
	git_reference_free(ref);
566
	return error;
schu committed
567 568
}

569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593
int git_note_commit_remove(
		git_oid *notes_commit_out,
		git_repository *repo,
		git_commit *notes_commit,
		const git_signature *author,
		const git_signature *committer,
		const git_oid *oid)
{
	int error;
	git_tree *tree = NULL;
	char target[GIT_OID_HEXSZ + 1];

	git_oid_tostr(target, sizeof(target), oid);

	if ((error = git_commit_tree(&tree, notes_commit)) < 0)
		goto cleanup;

	error = note_remove(notes_commit_out,
		repo, author, committer, NULL, tree, target, &notes_commit);

cleanup:
	git_tree_free(tree);
	return error;
}

594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624
int git_note_remove(git_repository *repo, const char *notes_ref_in,
		const git_signature *author, const git_signature *committer,
		const git_oid *oid)
{
	int error;
	char *notes_ref_target = NULL;
	git_commit *existing_notes_commit = NULL;
	git_oid new_notes_commit;
	git_reference *notes_ref = NULL;

	error = retrieve_note_commit(&existing_notes_commit, &notes_ref_target,
			repo, notes_ref_in);

	if (error < 0)
		goto cleanup;

	error = git_note_commit_remove(&new_notes_commit, repo,
			existing_notes_commit, author, committer, oid);
	if (error < 0)
		goto cleanup;

	error = git_reference_create(&notes_ref, repo, notes_ref_target,
			&new_notes_commit, 1, NULL);

cleanup:
	git__free(notes_ref_target);
	git_reference_free(notes_ref);
	git_commit_free(existing_notes_commit);
	return error;
}

625
int git_note_default_ref(git_buf *out, git_repository *repo)
626
{
627 628 629 630 631 632 633 634 635 636 637 638
	char *default_ref;
	int error;

	assert(out && repo);

	git_buf_sanitize(out);

	if ((error = note_get_default_ref(&default_ref, repo)) < 0)
		return error;

	git_buf_attach(out, default_ref, strlen(default_ref));
	return 0;
639 640
}

641 642 643 644 645 646 647 648 649 650 651 652
const git_signature *git_note_committer(const git_note *note)
{
	assert(note);
	return note->committer;
}

const git_signature *git_note_author(const git_note *note)
{
	assert(note);
	return note->author;
}

Ben Straub committed
653
const char * git_note_message(const git_note *note)
schu committed
654 655 656 657 658
{
	assert(note);
	return note->message;
}

659
const git_oid * git_note_id(const git_note *note)
schu committed
660 661
{
	assert(note);
662
	return &note->id;
schu committed
663 664 665 666 667 668 669
}

void git_note_free(git_note *note)
{
	if (note == NULL)
		return;

670 671
	git_signature_free(note->committer);
	git_signature_free(note->author);
schu committed
672 673 674
	git__free(note->message);
	git__free(note);
}
675 676 677

static int process_entry_path(
	const char* entry_path,
678
	git_oid *annotated_object_id)
679
{
680
	int error = 0;
681
	size_t i = 0, j = 0, len;
682 683
	git_buf buf = GIT_BUF_INIT;

684
	if ((error = git_buf_puts(&buf, entry_path)) < 0)
685
		goto cleanup;
686

687 688 689 690 691 692 693
	len = git_buf_len(&buf);

	while (i < len) {
		if (buf.ptr[i] == '/') {
			i++;
			continue;
		}
694

695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714
		if (git__fromhex(buf.ptr[i]) < 0) {
			/* This is not a note entry */
			goto cleanup;
		}

		if (i != j)
			buf.ptr[j] = buf.ptr[i];

		i++;
		j++;
	}

	buf.ptr[j] = '\0';
	buf.size = j;

	if (j != GIT_OID_HEXSZ) {
		/* This is not a note entry */
		goto cleanup;
	}

715
	error = git_oid_fromstr(annotated_object_id, buf.ptr);
716 717

cleanup:
718
	git_buf_dispose(&buf);
719 720 721 722
	return error;
}

int git_note_foreach(
Linquize committed
723 724 725 726
	git_repository *repo,
	const char *notes_ref,
	git_note_foreach_cb note_cb,
	void *payload)
727
{
Linquize committed
728 729 730
	int error;
	git_note_iterator *iter = NULL;
	git_oid note_id, annotated_id;
731

Linquize committed
732 733
	if ((error = git_note_iterator_new(&iter, repo, notes_ref)) < 0)
		return error;
734

735 736
	while (!(error = git_note_next(&note_id, &annotated_id, iter))) {
		if ((error = note_cb(&note_id, &annotated_id, payload)) != 0) {
737
			git_error_set_after_callback(error);
738 739 740
			break;
		}
	}
741

Linquize committed
742 743
	if (error == GIT_ITEROVER)
		error = 0;
744

Linquize committed
745 746
	git_note_iterator_free(iter);
	return error;
747
}
748

749 750 751 752 753 754 755 756
void git_note_iterator_free(git_note_iterator *it)
{
	if (it == NULL)
		return;

	git_iterator_free(it);
}

757
int git_note_commit_iterator_new(
758
	git_note_iterator **it,
759
	git_commit *notes_commit)
760 761
{
	int error;
762
	git_tree *tree;
763

764
	if ((error = git_commit_tree(&tree, notes_commit)) < 0)
765
		goto cleanup;
766

767
	if ((error = git_iterator_for_tree(it, tree, NULL)) < 0)
768
		git_iterator_free(*it);
769

770
cleanup:
771 772 773 774 775
	git_tree_free(tree);

	return error;
}

776
int git_note_iterator_new(
777
	git_note_iterator **it,
778 779
	git_repository *repo,
	const char *notes_ref_in)
780 781
{
	int error;
782 783
	git_commit *commit = NULL;
	char *notes_ref;
784

785 786
	error = retrieve_note_commit(&commit, &notes_ref, repo, notes_ref_in);
	if (error < 0)
787 788
		goto cleanup;

789
	error = git_note_commit_iterator_new(it, commit);
790 791

cleanup:
792 793
	git__free(notes_ref);
	git_commit_free(commit);
794 795 796 797

	return error;
}

798 799 800
int git_note_next(
	git_oid* note_id,
	git_oid* annotated_id,
801
	git_note_iterator *it)
802 803 804 805
{
	int error;
	const git_index_entry *item;

806
	if ((error = git_iterator_current(&item, it)) < 0)
807
		return error;
808

809
	git_oid_cpy(note_id, &item->id);
810

811 812
	if ((error = process_entry_path(item->path, annotated_id)) < 0)
		return error;
813

814 815 816 817
	if ((error = git_iterator_advance(NULL, it)) < 0 && error != GIT_ITEROVER)
		return error;

	return 0;
818
}