source src/notes.c
| Line | Flow | Count | Block(s) | Source |
|---|---|---|---|---|
| 1 | - | /* | ||
| 2 | - | * Copyright (C) the libgit2 contributors. All rights reserved. | ||
| 3 | - | * | ||
| 4 | - | * This file is part of libgit2, distributed under the GNU GPL v2 with | ||
| 5 | - | * a Linking Exception. For full terms see the included COPYING file. | ||
| 6 | - | */ | ||
| 7 | - | |||
| 8 | - | #include "notes.h" | ||
| 9 | - | |||
| 10 | - | #include "git2.h" | ||
| 11 | - | #include "refs.h" | ||
| 12 | - | #include "config.h" | ||
| 13 | - | #include "iterator.h" | ||
| 14 | - | #include "signature.h" | ||
| 15 | - | #include "blob.h" | ||
| 16 | - | |||
| 17 | 58 | 2 | static int note_error_notfound(void) | |
| 18 | - | { | ||
| 19 | 58 | 2 | git_error_set(GIT_ERROR_INVALID, "note could not be found"); | |
| 20 | 58 | 3 | return GIT_ENOTFOUND; | |
| 21 | - | } | ||
| 22 | - | |||
| 23 | ![]() |
114 | 2 | static int find_subtree_in_current_level( |
| 24 | - | git_tree **out, | ||
| 25 | - | git_repository *repo, | ||
| 26 | - | git_tree *parent, | ||
| 27 | - | const char *annotated_object_sha, | ||
| 28 | - | int fanout) | ||
| 29 | - | { | ||
| 30 | - | size_t i; | ||
| 31 | - | const git_tree_entry *entry; | ||
| 32 | - | |||
| 33 | 114 | 2 | *out = NULL; | |
| 34 | - | |||
| 35 | 114 | 2 | if (parent == NULL) | |
| 36 | 24 | 3 | return note_error_notfound(); | |
| 37 | - | |||
| 38 | 297 | 4,21-23 | for (i = 0; i < git_tree_entrycount(parent); i++) { | |
| 39 | 263 | 5 | entry = git_tree_entry_byindex(parent, i); | |
| 40 | - | |||
| 41 | 263 | 6-8 | if (!git__ishex(git_tree_entry_name(entry))) | |
| 42 | ##### | 9 | continue; | |
| 43 | - | |||
| 44 | 263 | 10,11 | if (S_ISDIR(git_tree_entry_filemode(entry)) | |
| 45 | 34 | 12,13 | && strlen(git_tree_entry_name(entry)) == 2 | |
| 46 | 34 | 14,15 | && !strncmp(git_tree_entry_name(entry), annotated_object_sha + fanout, 2)) | |
| 47 | 12 | 16,17 | return git_tree_lookup(out, repo, git_tree_entry_id(entry)); | |
| 48 | - | |||
| 49 | - | /* Not a DIR, so do we have an already existing blob? */ | ||
| 50 | 251 | 18,19 | if (!strcmp(git_tree_entry_name(entry), annotated_object_sha + fanout)) | |
| 51 | 44 | 20 | return GIT_EEXISTS; | |
| 52 | - | } | ||
| 53 | - | |||
| 54 | 34 | 24 | return note_error_notfound(); | |
| 55 | - | } | ||
| 56 | - | |||
| 57 | 46 | 2 | static int find_subtree_r(git_tree **out, git_tree *root, | |
| 58 | - | git_repository *repo, const char *target, int *fanout) | ||
| 59 | - | { | ||
| 60 | - | int error; | ||
| 61 | 46 | 2 | git_tree *subtree = NULL; | |
| 62 | - | |||
| 63 | 46 | 2 | *out = NULL; | |
| 64 | - | |||
| 65 | 46 | 2 | error = find_subtree_in_current_level(&subtree, repo, root, target, *fanout); | |
| 66 | 46 | 3 | if (error == GIT_EEXISTS) | |
| 67 | 35 | 4,5 | return git_tree_lookup(out, repo, git_tree_id(root)); | |
| 68 | - | |||
| 69 | 11 | 6 | if (error < 0) | |
| 70 | 6 | 7 | return error; | |
| 71 | - | |||
| 72 | 5 | 8 | *fanout += 2; | |
| 73 | 5 | 8 | error = find_subtree_r(out, subtree, repo, target, fanout); | |
| 74 | 5 | 9 | git_tree_free(subtree); | |
| 75 | - | |||
| 76 | 5 | 10 | return error; | |
| 77 | - | } | ||
| 78 | - | |||
| 79 | ![]() |
35 | 2 | static int find_blob(git_oid *blob, git_tree *tree, const char *target) |
| 80 | - | { | ||
| 81 | - | size_t i; | ||
| 82 | - | const git_tree_entry *entry; | ||
| 83 | - | |||
| 84 | 100 | 2,9-11 | for (i=0; i<git_tree_entrycount(tree); i++) { | |
| 85 | 100 | 3 | entry = git_tree_entry_byindex(tree, i); | |
| 86 | - | |||
| 87 | 100 | 4,5 | if (!strcmp(git_tree_entry_name(entry), target)) { | |
| 88 | - | /* found matching note object - return */ | ||
| 89 | - | |||
| 90 | 35 | 6,7 | git_oid_cpy(blob, git_tree_entry_id(entry)); | |
| 91 | 35 | 8 | return 0; | |
| 92 | - | } | ||
| 93 | - | } | ||
| 94 | - | |||
| 95 | ##### | 12 | return note_error_notfound(); | |
| 96 | - | } | ||
| 97 | - | |||
| 98 | ![]() |
63 | 2 | static int tree_write( |
| 99 | - | git_tree **out, | ||
| 100 | - | git_repository *repo, | ||
| 101 | - | git_tree *source_tree, | ||
| 102 | - | const git_oid *object_oid, | ||
| 103 | - | const char *treeentry_name, | ||
| 104 | - | unsigned int attributes) | ||
| 105 | - | { | ||
| 106 | - | int error; | ||
| 107 | 63 | 2 | git_treebuilder *tb = NULL; | |
| 108 | - | const git_tree_entry *entry; | ||
| 109 | - | git_oid tree_oid; | ||
| 110 | - | |||
| 111 | 63 | 2,3 | if ((error = git_treebuilder_new(&tb, repo, source_tree)) < 0) | |
| 112 | ##### | 4 | goto cleanup; | |
| 113 | - | |||
| 114 | 63 | 5 | if (object_oid) { | |
| 115 | 58 | 6,7 | if ((error = git_treebuilder_insert( | |
| 116 | - | &entry, tb, treeentry_name, object_oid, attributes)) < 0) | ||
| 117 | ##### | 8 | goto cleanup; | |
| 118 | - | } else { | ||
| 119 | 5 | 9,10 | if ((error = git_treebuilder_remove(tb, treeentry_name)) < 0) | |
| 120 | ##### | 11 | goto cleanup; | |
| 121 | - | } | ||
| 122 | - | |||
| 123 | 63 | 12,13 | if ((error = git_treebuilder_write(&tree_oid, tb)) < 0) | |
| 124 | ##### | 14 | goto cleanup; | |
| 125 | - | |||
| 126 | 63 | 15 | error = git_tree_lookup(out, repo, &tree_oid); | |
| 127 | - | |||
| 128 | - | cleanup: | ||
| 129 | 63 | 16 | git_treebuilder_free(tb); | |
| 130 | 63 | 17 | return error; | |
| 131 | - | } | ||
| 132 | - | |||
| 133 | ![]() |
68 | 2 | static int manipulate_note_in_tree_r( |
| 134 | - | git_tree **out, | ||
| 135 | - | git_repository *repo, | ||
| 136 | - | git_tree *parent, | ||
| 137 | - | git_oid *note_oid, | ||
| 138 | - | const char *annotated_object_sha, | ||
| 139 | - | int fanout, | ||
| 140 | - | int (*note_exists_cb)( | ||
| 141 | - | git_tree **out, | ||
| 142 | - | git_repository *repo, | ||
| 143 | - | git_tree *parent, | ||
| 144 | - | git_oid *note_oid, | ||
| 145 | - | const char *annotated_object_sha, | ||
| 146 | - | int fanout, | ||
| 147 | - | int current_error), | ||
| 148 | - | int (*note_notfound_cb)( | ||
| 149 | - | git_tree **out, | ||
| 150 | - | git_repository *repo, | ||
| 151 | - | git_tree *parent, | ||
| 152 | - | git_oid *note_oid, | ||
| 153 | - | const char *annotated_object_sha, | ||
| 154 | - | int fanout, | ||
| 155 | - | int current_error)) | ||
| 156 | - | { | ||
| 157 | - | int error; | ||
| 158 | 68 | 2 | git_tree *subtree = NULL, *new = NULL; | |
| 159 | - | char subtree_name[3]; | ||
| 160 | - | |||
| 161 | 68 | 2 | error = find_subtree_in_current_level( | |
| 162 | - | &subtree, repo, parent, annotated_object_sha, fanout); | ||
| 163 | - | |||
| 164 | 68 | 3 | if (error == GIT_EEXISTS) { | |
| 165 | 9 | 4 | error = note_exists_cb( | |
| 166 | - | out, repo, parent, note_oid, annotated_object_sha, fanout, error); | ||
| 167 | 9 | 5 | goto cleanup; | |
| 168 | - | } | ||
| 169 | - | |||
| 170 | 59 | 6 | if (error == GIT_ENOTFOUND) { | |
| 171 | 52 | 7 | error = note_notfound_cb( | |
| 172 | - | out, repo, parent, note_oid, annotated_object_sha, fanout, error); | ||
| 173 | 52 | 8 | goto cleanup; | |
| 174 | - | } | ||
| 175 | - | |||
| 176 | 7 | 9 | if (error < 0) | |
| 177 | ##### | 10 | goto cleanup; | |
| 178 | - | |||
| 179 | - | /* An existing fanout has been found, let's dig deeper */ | ||
| 180 | 7 | 11 | error = manipulate_note_in_tree_r( | |
| 181 | - | &new, repo, subtree, note_oid, annotated_object_sha, | ||
| 182 | - | fanout + 2, note_exists_cb, note_notfound_cb); | ||
| 183 | - | |||
| 184 | 7 | 12 | if (error < 0) | |
| 185 | 2 | 13 | goto cleanup; | |
| 186 | - | |||
| 187 | 5 | 14 | strncpy(subtree_name, annotated_object_sha + fanout, 2); | |
| 188 | 5 | 14 | subtree_name[2] = '\0'; | |
| 189 | - | |||
| 190 | 5 | 14,15 | error = tree_write(out, repo, parent, git_tree_id(new), | |
| 191 | - | subtree_name, GIT_FILEMODE_TREE); | ||
| 192 | - | |||
| 193 | - | |||
| 194 | - | cleanup: | ||
| 195 | 68 | 16 | git_tree_free(new); | |
| 196 | 68 | 17 | git_tree_free(subtree); | |
| 197 | 68 | 18 | return error; | |
| 198 | - | } | ||
| 199 | - | |||
| 200 | 5 | 2 | static int remove_note_in_tree_eexists_cb( | |
| 201 | - | git_tree **out, | ||
| 202 | - | git_repository *repo, | ||
| 203 | - | git_tree *parent, | ||
| 204 | - | git_oid *note_oid, | ||
| 205 | - | const char *annotated_object_sha, | ||
| 206 | - | int fanout, | ||
| 207 | - | int current_error) | ||
| 208 | - | { | ||
| 209 | - | GIT_UNUSED(note_oid); | ||
| 210 | - | GIT_UNUSED(current_error); | ||
| 211 | - | |||
| 212 | 5 | 2 | return tree_write(out, repo, parent, NULL, annotated_object_sha + fanout, 0); | |
| 213 | - | } | ||
| 214 | - | |||
| 215 | 1 | 2 | static int remove_note_in_tree_enotfound_cb( | |
| 216 | - | git_tree **out, | ||
| 217 | - | git_repository *repo, | ||
| 218 | - | git_tree *parent, | ||
| 219 | - | git_oid *note_oid, | ||
| 220 | - | const char *annotated_object_sha, | ||
| 221 | - | int fanout, | ||
| 222 | - | int current_error) | ||
| 223 | - | { | ||
| 224 | - | GIT_UNUSED(out); | ||
| 225 | - | GIT_UNUSED(repo); | ||
| 226 | - | GIT_UNUSED(parent); | ||
| 227 | - | GIT_UNUSED(note_oid); | ||
| 228 | - | GIT_UNUSED(fanout); | ||
| 229 | - | |||
| 230 | 1 | 2 | git_error_set(GIT_ERROR_REPOSITORY, "object '%s' has no note", annotated_object_sha); | |
| 231 | 1 | 3 | return current_error; | |
| 232 | - | } | ||
| 233 | - | |||
| 234 | 2 | 2 | static int insert_note_in_tree_eexists_cb(git_tree **out, | |
| 235 | - | git_repository *repo, | ||
| 236 | - | git_tree *parent, | ||
| 237 | - | git_oid *note_oid, | ||
| 238 | - | const char *annotated_object_sha, | ||
| 239 | - | int fanout, | ||
| 240 | - | int current_error) | ||
| 241 | - | { | ||
| 242 | - | GIT_UNUSED(out); | ||
| 243 | - | GIT_UNUSED(repo); | ||
| 244 | - | GIT_UNUSED(parent); | ||
| 245 | - | GIT_UNUSED(note_oid); | ||
| 246 | - | GIT_UNUSED(fanout); | ||
| 247 | - | |||
| 248 | 2 | 2 | git_error_set(GIT_ERROR_REPOSITORY, "note for '%s' exists already", annotated_object_sha); | |
| 249 | 2 | 3 | return current_error; | |
| 250 | - | } | ||
| 251 | - | |||
| 252 | 53 | 2 | static int insert_note_in_tree_enotfound_cb(git_tree **out, | |
| 253 | - | git_repository *repo, | ||
| 254 | - | git_tree *parent, | ||
| 255 | - | git_oid *note_oid, | ||
| 256 | - | const char *annotated_object_sha, | ||
| 257 | - | int fanout, | ||
| 258 | - | int current_error) | ||
| 259 | - | { | ||
| 260 | - | GIT_UNUSED(current_error); | ||
| 261 | - | |||
| 262 | - | /* No existing fanout at this level, insert in place */ | ||
| 263 | 53 | 2 | return tree_write( | |
| 264 | - | out, | ||
| 265 | - | repo, | ||
| 266 | - | parent, | ||
| 267 | - | note_oid, | ||
| 268 | - | annotated_object_sha + fanout, | ||
| 269 | - | GIT_FILEMODE_BLOB); | ||
| 270 | - | } | ||
| 271 | - | |||
| 272 | ![]() |
55 | 2 | static int note_write( |
| 273 | - | git_oid *notes_commit_out, | ||
| 274 | - | git_oid *notes_blob_out, | ||
| 275 | - | git_repository *repo, | ||
| 276 | - | const git_signature *author, | ||
| 277 | - | const git_signature *committer, | ||
| 278 | - | const char *notes_ref, | ||
| 279 | - | const char *note, | ||
| 280 | - | git_tree *commit_tree, | ||
| 281 | - | const char *target, | ||
| 282 | - | git_commit **parents, | ||
| 283 | - | int allow_note_overwrite) | ||
| 284 | - | { | ||
| 285 | - | int error; | ||
| 286 | - | git_oid oid; | ||
| 287 | 55 | 2 | git_tree *tree = NULL; | |
| 288 | - | |||
| 289 | - | /* TODO: should we apply filters? */ | ||
| 290 | - | /* create note object */ | ||
| 291 | 55 | 2,3 | if ((error = git_blob_create_from_buffer(&oid, repo, note, strlen(note))) < 0) | |
| 292 | ##### | 4 | goto cleanup; | |
| 293 | - | |||
| 294 | 55 | 5-9 | if ((error = manipulate_note_in_tree_r( | |
| 295 | - | &tree, repo, commit_tree, &oid, target, 0, | ||
| 296 | - | allow_note_overwrite ? insert_note_in_tree_enotfound_cb : insert_note_in_tree_eexists_cb, | ||
| 297 | - | insert_note_in_tree_enotfound_cb)) < 0) | ||
| 298 | 2 | 10 | goto cleanup; | |
| 299 | - | |||
| 300 | 53 | 11 | if (notes_blob_out) | |
| 301 | 45 | 12 | git_oid_cpy(notes_blob_out, &oid); | |
| 302 | - | |||
| 303 | - | |||
| 304 | 53 | 13 | error = git_commit_create(&oid, repo, notes_ref, author, committer, | |
| 305 | - | NULL, GIT_NOTES_DEFAULT_MSG_ADD, | ||
| 306 | 53 | 13 | tree, *parents == NULL ? 0 : 1, (const git_commit **) parents); | |
| 307 | - | |||
| 308 | 53 | 14 | if (notes_commit_out) | |
| 309 | 53 | 15 | git_oid_cpy(notes_commit_out, &oid); | |
| 310 | - | |||
| 311 | - | cleanup: | ||
| 312 | 55 | 16 | git_tree_free(tree); | |
| 313 | 55 | 17 | return error; | |
| 314 | - | } | ||
| 315 | - | |||
| 316 | ![]() |
35 | 2 | static int note_new( |
| 317 | - | git_note **out, | ||
| 318 | - | git_oid *note_oid, | ||
| 319 | - | git_commit *commit, | ||
| 320 | - | git_blob *blob) | ||
| 321 | - | { | ||
| 322 | 35 | 2 | git_note *note = NULL; | |
| 323 | - | git_object_size_t blobsize; | ||
| 324 | - | |||
| 325 | 35 | 2 | note = git__malloc(sizeof(git_note)); | |
| 326 | 35 | 3,4 | GIT_ERROR_CHECK_ALLOC(note); | |
| 327 | - | |||
| 328 | 35 | 5 | git_oid_cpy(¬e->id, note_oid); | |
| 329 | - | |||
| 330 | 35 | 6-8,11 | if (git_signature_dup(¬e->author, git_commit_author(commit)) < 0 || | |
| 331 | 35 | 9,10 | git_signature_dup(¬e->committer, git_commit_committer(commit)) < 0) | |
| 332 | ##### | 12 | return -1; | |
| 333 | - | |||
| 334 | 35 | 13 | blobsize = git_blob_rawsize(blob); | |
| 335 | 35 | 14-17 | GIT_ERROR_CHECK_BLOBSIZE(blobsize); | |
| 336 | - | |||
| 337 | 35 | 18,19 | note->message = git__strndup(git_blob_rawcontent(blob), (size_t)blobsize); | |
| 338 | 35 | 20,21 | GIT_ERROR_CHECK_ALLOC(note->message); | |
| 339 | - | |||
| 340 | 35 | 22 | *out = note; | |
| 341 | 35 | 22 | return 0; | |
| 342 | - | } | ||
| 343 | - | |||
| 344 | ![]() |
41 | 2 | static int note_lookup( |
| 345 | - | git_note **out, | ||
| 346 | - | git_repository *repo, | ||
| 347 | - | git_commit *commit, | ||
| 348 | - | git_tree *tree, | ||
| 349 | - | const char *target) | ||
| 350 | - | { | ||
| 351 | 41 | 2 | int error, fanout = 0; | |
| 352 | - | git_oid oid; | ||
| 353 | 41 | 2 | git_blob *blob = NULL; | |
| 354 | 41 | 2 | git_note *note = NULL; | |
| 355 | 41 | 2 | git_tree *subtree = NULL; | |
| 356 | - | |||
| 357 | 41 | 2,3 | if ((error = find_subtree_r(&subtree, tree, repo, target, &fanout)) < 0) | |
| 358 | 6 | 4 | goto cleanup; | |
| 359 | - | |||
| 360 | 35 | 5,6 | if ((error = find_blob(&oid, subtree, target + fanout)) < 0) | |
| 361 | ##### | 7 | goto cleanup; | |
| 362 | - | |||
| 363 | 35 | 8,9 | if ((error = git_blob_lookup(&blob, repo, &oid)) < 0) | |
| 364 | ##### | 10 | goto cleanup; | |
| 365 | - | |||
| 366 | 35 | 11,12 | if ((error = note_new(¬e, &oid, commit, blob)) < 0) | |
| 367 | ##### | 13 | goto cleanup; | |
| 368 | - | |||
| 369 | 35 | 14 | *out = note; | |
| 370 | - | |||
| 371 | - | cleanup: | ||
| 372 | 41 | 15 | git_tree_free(subtree); | |
| 373 | 41 | 16 | git_blob_free(blob); | |
| 374 | 41 | 17 | return error; | |
| 375 | - | } | ||
| 376 | - | |||
| 377 | ![]() |
6 | 2 | static int note_remove( |
| 378 | - | git_oid *notes_commit_out, | ||
| 379 | - | git_repository *repo, | ||
| 380 | - | const git_signature *author, const git_signature *committer, | ||
| 381 | - | const char *notes_ref, git_tree *tree, | ||
| 382 | - | const char *target, git_commit **parents) | ||
| 383 | - | { | ||
| 384 | - | int error; | ||
| 385 | 6 | 2 | git_tree *tree_after_removal = NULL; | |
| 386 | - | git_oid oid; | ||
| 387 | - | |||
| 388 | 6 | 2,3 | if ((error = manipulate_note_in_tree_r( | |
| 389 | - | &tree_after_removal, repo, tree, NULL, target, 0, | ||
| 390 | - | remove_note_in_tree_eexists_cb, remove_note_in_tree_enotfound_cb)) < 0) | ||
| 391 | 1 | 4 | goto cleanup; | |
| 392 | - | |||
| 393 | 5 | 5 | error = git_commit_create(&oid, repo, notes_ref, author, committer, | |
| 394 | - | NULL, GIT_NOTES_DEFAULT_MSG_RM, | ||
| 395 | - | tree_after_removal, | ||
| 396 | 5 | 5 | *parents == NULL ? 0 : 1, | |
| 397 | - | (const git_commit **) parents); | ||
| 398 | - | |||
| 399 | 5 | 6 | if (error < 0) | |
| 400 | ##### | 7 | goto cleanup; | |
| 401 | - | |||
| 402 | 5 | 8 | if (notes_commit_out) | |
| 403 | 5 | 9 | git_oid_cpy(notes_commit_out, &oid); | |
| 404 | - | |||
| 405 | - | cleanup: | ||
| 406 | 6 | 10 | git_tree_free(tree_after_removal); | |
| 407 | 6 | 11 | return error; | |
| 408 | - | } | ||
| 409 | - | |||
| 410 | ![]() |
15 | 2 | static int note_get_default_ref(char **out, git_repository *repo) |
| 411 | - | { | ||
| 412 | - | git_config *cfg; | ||
| 413 | 15 | 2 | int ret = git_repository_config__weakptr(&cfg, repo); | |
| 414 | - | |||
| 415 | 15 | 3-5 | *out = (ret != 0) ? NULL : git_config__get_string_force( | |
| 416 | - | cfg, "core.notesref", GIT_NOTES_DEFAULT_REF); | ||
| 417 | - | |||
| 418 | 15 | 6 | return ret; | |
| 419 | - | } | ||
| 420 | - | |||
| 421 | 97 | 2 | static int normalize_namespace(char **out, git_repository *repo, const char *notes_ref) | |
| 422 | - | { | ||
| 423 | 97 | 2 | if (notes_ref) { | |
| 424 | 85 | 3 | *out = git__strdup(notes_ref); | |
| 425 | 85 | 4,5 | GIT_ERROR_CHECK_ALLOC(*out); | |
| 426 | 85 | 6 | return 0; | |
| 427 | - | } | ||
| 428 | - | |||
| 429 | 12 | 7 | return note_get_default_ref(out, repo); | |
| 430 | - | } | ||
| 431 | - | |||
| 432 | 97 | 2 | 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 | - | git_oid oid; | ||
| 440 | - | |||
| 441 | 97 | 2,3 | if ((error = normalize_namespace(notes_ref_out, repo, notes_ref)) < 0) | |
| 442 | ##### | 4 | return error; | |
| 443 | - | |||
| 444 | 97 | 5,6 | if ((error = git_reference_name_to_id(&oid, repo, *notes_ref_out)) < 0) | |
| 445 | 20 | 7 | return error; | |
| 446 | - | |||
| 447 | 77 | 8,9 | if (git_commit_lookup(commit_out, repo, &oid) < 0) | |
| 448 | ##### | 10 | return error; | |
| 449 | - | |||
| 450 | 77 | 11 | return 0; | |
| 451 | - | } | ||
| 452 | - | |||
| 453 | 41 | 2 | int git_note_commit_read( | |
| 454 | - | git_note **out, | ||
| 455 | - | git_repository *repo, | ||
| 456 | - | git_commit *notes_commit, | ||
| 457 | - | const git_oid *oid) | ||
| 458 | - | { | ||
| 459 | - | int error; | ||
| 460 | 41 | 2 | git_tree *tree = NULL; | |
| 461 | - | char target[GIT_OID_HEXSZ + 1]; | ||
| 462 | - | |||
| 463 | 41 | 2 | git_oid_tostr(target, sizeof(target), oid); | |
| 464 | - | |||
| 465 | 41 | 3,4 | if ((error = git_commit_tree(&tree, notes_commit)) < 0) | |
| 466 | ##### | 5 | goto cleanup; | |
| 467 | - | |||
| 468 | 41 | 6 | error = note_lookup(out, repo, notes_commit, tree, target); | |
| 469 | - | |||
| 470 | - | cleanup: | ||
| 471 | 41 | 7 | git_tree_free(tree); | |
| 472 | 41 | 8 | return error; | |
| 473 | - | } | ||
| 474 | - | |||
| 475 | 37 | 2 | int git_note_read(git_note **out, git_repository *repo, | |
| 476 | - | const char *notes_ref_in, const git_oid *oid) | ||
| 477 | - | { | ||
| 478 | - | int error; | ||
| 479 | 37 | 2 | char *notes_ref = NULL; | |
| 480 | 37 | 2 | git_commit *commit = NULL; | |
| 481 | - | |||
| 482 | 37 | 2 | error = retrieve_note_commit(&commit, ¬es_ref, repo, notes_ref_in); | |
| 483 | - | |||
| 484 | 37 | 3 | if (error < 0) | |
| 485 | ##### | 4 | goto cleanup; | |
| 486 | - | |||
| 487 | 37 | 5 | error = git_note_commit_read(out, repo, commit, oid); | |
| 488 | - | |||
| 489 | - | cleanup: | ||
| 490 | 37 | 6 | git__free(notes_ref); | |
| 491 | 37 | 7 | git_commit_free(commit); | |
| 492 | 37 | 8 | return error; | |
| 493 | - | } | ||
| 494 | - | |||
| 495 | ![]() |
55 | 2 | int git_note_commit_create( |
| 496 | - | git_oid *notes_commit_out, | ||
| 497 | - | git_oid *notes_blob_out, | ||
| 498 | - | git_repository *repo, | ||
| 499 | - | git_commit *parent, | ||
| 500 | - | const git_signature *author, | ||
| 501 | - | const git_signature *committer, | ||
| 502 | - | const git_oid *oid, | ||
| 503 | - | const char *note, | ||
| 504 | - | int allow_note_overwrite) | ||
| 505 | - | { | ||
| 506 | - | int error; | ||
| 507 | 55 | 2 | git_tree *tree = NULL; | |
| 508 | - | char target[GIT_OID_HEXSZ + 1]; | ||
| 509 | - | |||
| 510 | 55 | 2 | git_oid_tostr(target, sizeof(target), oid); | |
| 511 | - | |||
| 512 | 55 | 3-5 | if (parent != NULL && (error = git_commit_tree(&tree, parent)) < 0) | |
| 513 | ##### | 6 | goto cleanup; | |
| 514 | - | |||
| 515 | 55 | 7 | error = note_write(notes_commit_out, notes_blob_out, repo, author, | |
| 516 | - | committer, NULL, note, tree, target, &parent, allow_note_overwrite); | ||
| 517 | - | |||
| 518 | 55 | 8 | if (error < 0) | |
| 519 | 2 | 9 | goto cleanup; | |
| 520 | - | |||
| 521 | - | cleanup: | ||
| 522 | 55 | 10 | git_tree_free(tree); | |
| 523 | 55 | 11 | return error; | |
| 524 | - | } | ||
| 525 | - | |||
| 526 | ![]() |
47 | 2 | int git_note_create( |
| 527 | - | git_oid *out, | ||
| 528 | - | git_repository *repo, | ||
| 529 | - | const char *notes_ref_in, | ||
| 530 | - | const git_signature *author, | ||
| 531 | - | const git_signature *committer, | ||
| 532 | - | const git_oid *oid, | ||
| 533 | - | const char *note, | ||
| 534 | - | int allow_note_overwrite) | ||
| 535 | - | { | ||
| 536 | - | int error; | ||
| 537 | 47 | 2 | char *notes_ref = NULL; | |
| 538 | 47 | 2 | git_commit *existing_notes_commit = NULL; | |
| 539 | 47 | 2 | git_reference *ref = NULL; | |
| 540 | - | git_oid notes_blob_oid, notes_commit_oid; | ||
| 541 | - | |||
| 542 | 47 | 2 | error = retrieve_note_commit(&existing_notes_commit, ¬es_ref, | |
| 543 | - | repo, notes_ref_in); | ||
| 544 | - | |||
| 545 | 47 | 3,4 | if (error < 0 && error != GIT_ENOTFOUND) | |
| 546 | ##### | 5 | goto cleanup; | |
| 547 | - | |||
| 548 | 47 | 6 | error = git_note_commit_create(¬es_commit_oid, | |
| 549 | - | ¬es_blob_oid, | ||
| 550 | - | repo, existing_notes_commit, author, | ||
| 551 | - | committer, oid, note, | ||
| 552 | - | allow_note_overwrite); | ||
| 553 | 47 | 7 | if (error < 0) | |
| 554 | 2 | 8 | goto cleanup; | |
| 555 | - | |||
| 556 | 45 | 9 | error = git_reference_create(&ref, repo, notes_ref, | |
| 557 | - | ¬es_commit_oid, 1, NULL); | ||
| 558 | - | |||
| 559 | 45 | 10 | if (out != NULL) | |
| 560 | 45 | 11 | git_oid_cpy(out, ¬es_blob_oid); | |
| 561 | - | |||
| 562 | - | cleanup: | ||
| 563 | 47 | 12 | git__free(notes_ref); | |
| 564 | 47 | 13 | git_commit_free(existing_notes_commit); | |
| 565 | 47 | 14 | git_reference_free(ref); | |
| 566 | 47 | 15 | return error; | |
| 567 | - | } | ||
| 568 | - | |||
| 569 | 6 | 2 | int git_note_commit_remove( | |
| 570 | - | git_oid *notes_commit_out, | ||
| 571 | - | git_repository *repo, | ||
| 572 | - | git_commit *notes_commit, | ||
| 573 | - | const git_signature *author, | ||
| 574 | - | const git_signature *committer, | ||
| 575 | - | const git_oid *oid) | ||
| 576 | - | { | ||
| 577 | - | int error; | ||
| 578 | 6 | 2 | git_tree *tree = NULL; | |
| 579 | - | char target[GIT_OID_HEXSZ + 1]; | ||
| 580 | - | |||
| 581 | 6 | 2 | git_oid_tostr(target, sizeof(target), oid); | |
| 582 | - | |||
| 583 | 6 | 3,4 | if ((error = git_commit_tree(&tree, notes_commit)) < 0) | |
| 584 | ##### | 5 | goto cleanup; | |
| 585 | - | |||
| 586 | 6 | 6 | error = note_remove(notes_commit_out, | |
| 587 | - | repo, author, committer, NULL, tree, target, ¬es_commit); | ||
| 588 | - | |||
| 589 | - | cleanup: | ||
| 590 | 6 | 7 | git_tree_free(tree); | |
| 591 | 6 | 8 | return error; | |
| 592 | - | } | ||
| 593 | - | |||
| 594 | 4 | 2 | int git_note_remove(git_repository *repo, const char *notes_ref_in, | |
| 595 | - | const git_signature *author, const git_signature *committer, | ||
| 596 | - | const git_oid *oid) | ||
| 597 | - | { | ||
| 598 | - | int error; | ||
| 599 | 4 | 2 | char *notes_ref_target = NULL; | |
| 600 | 4 | 2 | git_commit *existing_notes_commit = NULL; | |
| 601 | - | git_oid new_notes_commit; | ||
| 602 | 4 | 2 | git_reference *notes_ref = NULL; | |
| 603 | - | |||
| 604 | 4 | 2 | error = retrieve_note_commit(&existing_notes_commit, ¬es_ref_target, | |
| 605 | - | repo, notes_ref_in); | ||
| 606 | - | |||
| 607 | 4 | 3 | if (error < 0) | |
| 608 | ##### | 4 | goto cleanup; | |
| 609 | - | |||
| 610 | 4 | 5 | error = git_note_commit_remove(&new_notes_commit, repo, | |
| 611 | - | existing_notes_commit, author, committer, oid); | ||
| 612 | 4 | 6 | if (error < 0) | |
| 613 | 1 | 7 | goto cleanup; | |
| 614 | - | |||
| 615 | 3 | 8 | error = git_reference_create(¬es_ref, repo, notes_ref_target, | |
| 616 | - | &new_notes_commit, 1, NULL); | ||
| 617 | - | |||
| 618 | - | cleanup: | ||
| 619 | 4 | 9 | git__free(notes_ref_target); | |
| 620 | 4 | 10 | git_reference_free(notes_ref); | |
| 621 | 4 | 11 | git_commit_free(existing_notes_commit); | |
| 622 | 4 | 12 | return error; | |
| 623 | - | } | ||
| 624 | - | |||
| 625 | ![]() |
3 | 2 | int git_note_default_ref(git_buf *out, git_repository *repo) |
| 626 | - | { | ||
| 627 | - | char *default_ref; | ||
| 628 | - | int error; | ||
| 629 | - | |||
| 630 | 3 | 2-4 | assert(out && repo); | |
| 631 | - | |||
| 632 | 3 | 5 | git_buf_sanitize(out); | |
| 633 | - | |||
| 634 | 3 | 6,7 | if ((error = note_get_default_ref(&default_ref, repo)) < 0) | |
| 635 | ##### | 8 | return error; | |
| 636 | - | |||
| 637 | 3 | 9 | git_buf_attach(out, default_ref, strlen(default_ref)); | |
| 638 | 3 | 10 | return 0; | |
| 639 | - | } | ||
| 640 | - | |||
| 641 | ##### | 2 | const git_signature *git_note_committer(const git_note *note) | |
| 642 | - | { | ||
| 643 | ##### | 2,3 | assert(note); | |
| 644 | ##### | 4 | return note->committer; | |
| 645 | - | } | ||
| 646 | - | |||
| 647 | 2 | 2 | const git_signature *git_note_author(const git_note *note) | |
| 648 | - | { | ||
| 649 | 2 | 2,3 | assert(note); | |
| 650 | 2 | 4 | return note->author; | |
| 651 | - | } | ||
| 652 | - | |||
| 653 | 24 | 2 | const char * git_note_message(const git_note *note) | |
| 654 | - | { | ||
| 655 | 24 | 2,3 | assert(note); | |
| 656 | 24 | 4 | return note->message; | |
| 657 | - | } | ||
| 658 | - | |||
| 659 | 8 | 2 | const git_oid * git_note_id(const git_note *note) | |
| 660 | - | { | ||
| 661 | 8 | 2,3 | assert(note); | |
| 662 | 8 | 4 | return ¬e->id; | |
| 663 | - | } | ||
| 664 | - | |||
| 665 | 38 | 2 | void git_note_free(git_note *note) | |
| 666 | - | { | ||
| 667 | 38 | 2 | if (note == NULL) | |
| 668 | 38 | 3,8 | return; | |
| 669 | - | |||
| 670 | 35 | 4 | git_signature_free(note->committer); | |
| 671 | 35 | 5 | git_signature_free(note->author); | |
| 672 | 35 | 6 | git__free(note->message); | |
| 673 | 35 | 7 | git__free(note); | |
| 674 | - | } | ||
| 675 | - | |||
| 676 | ![]() |
17 | 2 | static int process_entry_path( |
| 677 | - | const char* entry_path, | ||
| 678 | - | git_oid *annotated_object_id) | ||
| 679 | - | { | ||
| 680 | 17 | 2 | int error = 0; | |
| 681 | 17 | 2 | size_t i = 0, j = 0, len; | |
| 682 | 17 | 2 | git_buf buf = GIT_BUF_INIT; | |
| 683 | - | |||
| 684 | 17 | 2,3 | if ((error = git_buf_puts(&buf, entry_path)) < 0) | |
| 685 | ##### | 4 | goto cleanup; | |
| 686 | - | |||
| 687 | 17 | 5 | len = git_buf_len(&buf); | |
| 688 | - | |||
| 689 | 697 | 6,15 | while (i < len) { | |
| 690 | 680 | 7 | if (buf.ptr[i] == '/') { | |
| 691 | ##### | 8 | i++; | |
| 692 | ##### | 8 | continue; | |
| 693 | - | } | ||
| 694 | - | |||
| 695 | 680 | 9,10 | if (git__fromhex(buf.ptr[i]) < 0) { | |
| 696 | - | /* This is not a note entry */ | ||
| 697 | ##### | 11 | goto cleanup; | |
| 698 | - | } | ||
| 699 | - | |||
| 700 | 680 | 12 | if (i != j) | |
| 701 | ##### | 13 | buf.ptr[j] = buf.ptr[i]; | |
| 702 | - | |||
| 703 | 680 | 14 | i++; | |
| 704 | 680 | 14 | j++; | |
| 705 | - | } | ||
| 706 | - | |||
| 707 | 17 | 16 | buf.ptr[j] = '\0'; | |
| 708 | 17 | 16 | buf.size = j; | |
| 709 | - | |||
| 710 | 17 | 16 | if (j != GIT_OID_HEXSZ) { | |
| 711 | - | /* This is not a note entry */ | ||
| 712 | ##### | 17 | goto cleanup; | |
| 713 | - | } | ||
| 714 | - | |||
| 715 | 17 | 18 | error = git_oid_fromstr(annotated_object_id, buf.ptr); | |
| 716 | - | |||
| 717 | - | cleanup: | ||
| 718 | 17 | 19 | git_buf_dispose(&buf); | |
| 719 | 17 | 20 | return error; | |
| 720 | - | } | ||
| 721 | - | |||
| 722 | ![]() |
6 | 2 | int git_note_foreach( |
| 723 | - | git_repository *repo, | ||
| 724 | - | const char *notes_ref, | ||
| 725 | - | git_note_foreach_cb note_cb, | ||
| 726 | - | void *payload) | ||
| 727 | - | { | ||
| 728 | - | int error; | ||
| 729 | 6 | 2 | git_note_iterator *iter = NULL; | |
| 730 | - | git_oid note_id, annotated_id; | ||
| 731 | - | |||
| 732 | 6 | 2,3 | if ((error = git_note_iterator_new(&iter, repo, notes_ref)) < 0) | |
| 733 | 1 | 4 | return error; | |
| 734 | - | |||
| 735 | 15 | 5,10,11 | while (!(error = git_note_next(¬e_id, &annotated_id, iter))) { | |
| 736 | 11 | 6,7 | if ((error = note_cb(¬e_id, &annotated_id, payload)) != 0) { | |
| 737 | 1 | 8 | git_error_set_after_callback(error); | |
| 738 | 1 | 9 | break; | |
| 739 | - | } | ||
| 740 | - | } | ||
| 741 | - | |||
| 742 | 5 | 12 | if (error == GIT_ITEROVER) | |
| 743 | 4 | 13 | error = 0; | |
| 744 | - | |||
| 745 | 5 | 14 | git_note_iterator_free(iter); | |
| 746 | 5 | 15 | return error; | |
| 747 | - | } | ||
| 748 | - | |||
| 749 | 8 | 2 | void git_note_iterator_free(git_note_iterator *it) | |
| 750 | - | { | ||
| 751 | 8 | 2 | if (it == NULL) | |
| 752 | 8 | 3,5 | return; | |
| 753 | - | |||
| 754 | 8 | 4 | git_iterator_free(it); | |
| 755 | - | } | ||
| 756 | - | |||
| 757 | 8 | 2 | 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 | 8 | 2,3 | if ((error = git_commit_tree(&tree, notes_commit)) < 0) | |
| 765 | ##### | 4 | goto cleanup; | |
| 766 | - | |||
| 767 | 8 | 5,6 | if ((error = git_iterator_for_tree(it, tree, NULL)) < 0) | |
| 768 | ##### | 7 | git_iterator_free(*it); | |
| 769 | - | |||
| 770 | - | cleanup: | ||
| 771 | 8 | 8 | git_tree_free(tree); | |
| 772 | - | |||
| 773 | 8 | 9 | return error; | |
| 774 | - | } | ||
| 775 | - | |||
| 776 | 9 | 2 | int git_note_iterator_new( | |
| 777 | - | git_note_iterator **it, | ||
| 778 | - | git_repository *repo, | ||
| 779 | - | const char *notes_ref_in) | ||
| 780 | - | { | ||
| 781 | - | int error; | ||
| 782 | 9 | 2 | git_commit *commit = NULL; | |
| 783 | - | char *notes_ref; | ||
| 784 | - | |||
| 785 | 9 | 2 | error = retrieve_note_commit(&commit, ¬es_ref, repo, notes_ref_in); | |
| 786 | 9 | 3 | if (error < 0) | |
| 787 | 2 | 4 | goto cleanup; | |
| 788 | - | |||
| 789 | 7 | 5 | error = git_note_commit_iterator_new(it, commit); | |
| 790 | - | |||
| 791 | - | cleanup: | ||
| 792 | 9 | 6 | git__free(notes_ref); | |
| 793 | 9 | 7 | git_commit_free(commit); | |
| 794 | - | |||
| 795 | 9 | 8 | return error; | |
| 796 | - | } | ||
| 797 | - | |||
| 798 | ![]() |
24 | 2 | int git_note_next( |
| 799 | - | git_oid* note_id, | ||
| 800 | - | git_oid* annotated_id, | ||
| 801 | - | git_note_iterator *it) | ||
| 802 | - | { | ||
| 803 | - | int error; | ||
| 804 | - | const git_index_entry *item; | ||
| 805 | - | |||
| 806 | 24 | 2,3 | if ((error = git_iterator_current(&item, it)) < 0) | |
| 807 | 7 | 4 | return error; | |
| 808 | - | |||
| 809 | 17 | 5 | git_oid_cpy(note_id, &item->id); | |
| 810 | - | |||
| 811 | 17 | 6,7 | if ((error = process_entry_path(item->path, annotated_id)) < 0) | |
| 812 | ##### | 8 | return error; | |
| 813 | - | |||
| 814 | 17 | 9-11 | if ((error = git_iterator_advance(NULL, it)) < 0 && error != GIT_ITEROVER) | |
| 815 | ##### | 12 | return error; | |
| 816 | - | |||
| 817 | 17 | 13 | return 0; | |
| 818 | - | } |