source src/refs.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 "refs.h" | ||
| 9 | - | |||
| 10 | - | #include "hash.h" | ||
| 11 | - | #include "repository.h" | ||
| 12 | - | #include "futils.h" | ||
| 13 | - | #include "filebuf.h" | ||
| 14 | - | #include "pack.h" | ||
| 15 | - | #include "reflog.h" | ||
| 16 | - | #include "refdb.h" | ||
| 17 | - | |||
| 18 | - | #include <git2/tag.h> | ||
| 19 | - | #include <git2/object.h> | ||
| 20 | - | #include <git2/oid.h> | ||
| 21 | - | #include <git2/branch.h> | ||
| 22 | - | #include <git2/refs.h> | ||
| 23 | - | #include <git2/refdb.h> | ||
| 24 | - | #include <git2/sys/refs.h> | ||
| 25 | - | #include <git2/signature.h> | ||
| 26 | - | #include <git2/commit.h> | ||
| 27 | - | |||
| 28 | - | bool git_reference__enable_symbolic_ref_target_validation = true; | ||
| 29 | - | |||
| 30 | - | #define DEFAULT_NESTING_LEVEL 5 | ||
| 31 | - | #define MAX_NESTING_LEVEL 10 | ||
| 32 | - | |||
| 33 | - | enum { | ||
| 34 | - | GIT_PACKREF_HAS_PEEL = 1, | ||
| 35 | - | GIT_PACKREF_WAS_LOOSE = 2 | ||
| 36 | - | }; | ||
| 37 | - | |||
| 38 | ![]() |
- | 2 | suppressed: function cannot be solved alloc_ref (automatic due to inconsistent arc counts in .gcda files)static git_reference *alloc_ref(const char *name) |
| 39 | - | { | ||
| 40 | - | 2 | suppressed: function cannot be solved alloc_ref (automatic due to inconsistent arc counts in .gcda files) git_reference *ref = NULL; | |
| 41 | - | 2 | suppressed: function cannot be solved alloc_ref (automatic due to inconsistent arc counts in .gcda files) size_t namelen = strlen(name), reflen; | |
| 42 | - | |||
| 43 | - | 2-7,9,11-13 | suppressed: function cannot be solved alloc_ref (automatic due to inconsistent arc counts in .gcda files) if (!GIT_ADD_SIZET_OVERFLOW(&reflen, sizeof(git_reference), namelen) && | |
| 44 | - | 8,10,14,15 | suppressed: function cannot be solved alloc_ref (automatic due to inconsistent arc counts in .gcda files) !GIT_ADD_SIZET_OVERFLOW(&reflen, reflen, 1) && | |
| 45 | - | 14 | suppressed: function cannot be solved alloc_ref (automatic due to inconsistent arc counts in .gcda files) (ref = git__calloc(1, reflen)) != NULL) | |
| 46 | - | 16 | suppressed: function cannot be solved alloc_ref (automatic due to inconsistent arc counts in .gcda files) memcpy(ref->name, name, namelen + 1); | |
| 47 | - | |||
| 48 | - | 17 | suppressed: function cannot be solved alloc_ref (automatic due to inconsistent arc counts in .gcda files) return ref; | |
| 49 | - | } | ||
| 50 | - | |||
| 51 | ![]() |
8844 | 2 | git_reference *git_reference__alloc_symbolic( |
| 52 | - | const char *name, const char *target) | ||
| 53 | - | { | ||
| 54 | - | git_reference *ref; | ||
| 55 | - | |||
| 56 | 8844 | 2-4 | assert(name && target); | |
| 57 | - | |||
| 58 | 8844 | 5 | ref = alloc_ref(name); | |
| 59 | 8844 | 6 | if (!ref) | |
| 60 | ##### | 7 | return NULL; | |
| 61 | - | |||
| 62 | 8844 | 8 | ref->type = GIT_REFERENCE_SYMBOLIC; | |
| 63 | - | |||
| 64 | 8844 | 8,9 | if ((ref->target.symbolic = git__strdup(target)) == NULL) { | |
| 65 | ##### | 10 | git__free(ref); | |
| 66 | ##### | 11 | return NULL; | |
| 67 | - | } | ||
| 68 | - | |||
| 69 | 8844 | 12 | return ref; | |
| 70 | - | } | ||
| 71 | - | |||
| 72 | ![]() |
- | 2 | suppressed: function cannot be solved git_reference__alloc (automatic due to inconsistent arc counts in .gcda files)git_reference *git_reference__alloc( |
| 73 | - | const char *name, | ||
| 74 | - | const git_oid *oid, | ||
| 75 | - | const git_oid *peel) | ||
| 76 | - | { | ||
| 77 | - | git_reference *ref; | ||
| 78 | - | |||
| 79 | - | 2-4 | suppressed: function cannot be solved git_reference__alloc (automatic due to inconsistent arc counts in .gcda files) assert(name && oid); | |
| 80 | - | |||
| 81 | - | 5 | suppressed: function cannot be solved git_reference__alloc (automatic due to inconsistent arc counts in .gcda files) ref = alloc_ref(name); | |
| 82 | - | 6 | suppressed: function cannot be solved git_reference__alloc (automatic due to inconsistent arc counts in .gcda files) if (!ref) | |
| 83 | - | 7 | suppressed: function cannot be solved git_reference__alloc (automatic due to inconsistent arc counts in .gcda files) return NULL; | |
| 84 | - | |||
| 85 | - | 8 | suppressed: function cannot be solved git_reference__alloc (automatic due to inconsistent arc counts in .gcda files) ref->type = GIT_REFERENCE_DIRECT; | |
| 86 | - | 8 | suppressed: function cannot be solved git_reference__alloc (automatic due to inconsistent arc counts in .gcda files) git_oid_cpy(&ref->target.oid, oid); | |
| 87 | - | |||
| 88 | - | 9 | suppressed: function cannot be solved git_reference__alloc (automatic due to inconsistent arc counts in .gcda files) if (peel != NULL) | |
| 89 | - | 10 | suppressed: function cannot be solved git_reference__alloc (automatic due to inconsistent arc counts in .gcda files) git_oid_cpy(&ref->peel, peel); | |
| 90 | - | |||
| 91 | - | 11 | suppressed: function cannot be solved git_reference__alloc (automatic due to inconsistent arc counts in .gcda files) return ref; | |
| 92 | - | } | ||
| 93 | - | |||
| 94 | ![]() |
38 | 2 | git_reference *git_reference__realloc( |
| 95 | - | git_reference **ptr_to_ref, const char *name) | ||
| 96 | - | { | ||
| 97 | - | size_t namelen, reflen; | ||
| 98 | 38 | 2 | git_reference *rewrite = NULL; | |
| 99 | - | |||
| 100 | 38 | 2-4 | assert(ptr_to_ref && name); | |
| 101 | - | |||
| 102 | 38 | 5 | namelen = strlen(name); | |
| 103 | - | |||
| 104 | 38 | 5-10,12,14-16 | if (!GIT_ADD_SIZET_OVERFLOW(&reflen, sizeof(git_reference), namelen) && | |
| 105 | 38 | 11,13,17,18 | !GIT_ADD_SIZET_OVERFLOW(&reflen, reflen, 1) && | |
| 106 | 38 | 17 | (rewrite = git__realloc(*ptr_to_ref, reflen)) != NULL) | |
| 107 | 38 | 19 | memcpy(rewrite->name, name, namelen + 1); | |
| 108 | - | |||
| 109 | 38 | 20 | *ptr_to_ref = NULL; | |
| 110 | - | |||
| 111 | 38 | 20 | return rewrite; | |
| 112 | - | } | ||
| 113 | - | |||
| 114 | 3 | 2 | int git_reference_dup(git_reference **dest, git_reference *source) | |
| 115 | - | { | ||
| 116 | 3 | 2 | if (source->type == GIT_REFERENCE_SYMBOLIC) | |
| 117 | 1 | 3,4 | *dest = git_reference__alloc_symbolic(source->name, source->target.symbolic); | |
| 118 | - | else | ||
| 119 | 2 | 5,6 | *dest = git_reference__alloc(source->name, &source->target.oid, &source->peel); | |
| 120 | - | |||
| 121 | 3 | 7,8 | GIT_ERROR_CHECK_ALLOC(*dest); | |
| 122 | - | |||
| 123 | 3 | 9 | (*dest)->db = source->db; | |
| 124 | 3 | 9 | GIT_REFCOUNT_INC((*dest)->db); | |
| 125 | - | |||
| 126 | 3 | 10 | return 0; | |
| 127 | - | } | ||
| 128 | - | |||
| 129 | 37388 | 2 | void git_reference_free(git_reference *reference) | |
| 130 | - | { | ||
| 131 | 37388 | 2 | if (reference == NULL) | |
| 132 | 37410 | 3,12 | return; | |
| 133 | - | |||
| 134 | 26941 | 4 | if (reference->type == GIT_REFERENCE_SYMBOLIC) | |
| 135 | 8844 | 5 | git__free(reference->target.symbolic); | |
| 136 | - | |||
| 137 | 26947 | 6 | if (reference->db) | |
| 138 | 25886 | 7-10 | GIT_REFCOUNT_DEC(reference->db, git_refdb__free); | |
| 139 | - | |||
| 140 | 26958 | 11 | git__free(reference); | |
| 141 | - | } | ||
| 142 | - | |||
| 143 | 88 | 2 | int git_reference_delete(git_reference *ref) | |
| 144 | - | { | ||
| 145 | 88 | 2 | const git_oid *old_id = NULL; | |
| 146 | 88 | 2 | const char *old_target = NULL; | |
| 147 | - | |||
| 148 | 88 | 2 | if (!strcmp(ref->name, "HEAD")) { | |
| 149 | 2 | 3 | git_error_set(GIT_ERROR_REFERENCE, "cannot delete HEAD"); | |
| 150 | 2 | 4 | return GIT_ERROR; | |
| 151 | - | } | ||
| 152 | - | |||
| 153 | 86 | 5 | if (ref->type == GIT_REFERENCE_DIRECT) | |
| 154 | 83 | 6 | old_id = &ref->target.oid; | |
| 155 | - | else | ||
| 156 | 3 | 7 | old_target = ref->target.symbolic; | |
| 157 | - | |||
| 158 | 86 | 8 | return git_refdb_delete(ref->db, ref->name, old_id, old_target); | |
| 159 | - | } | ||
| 160 | - | |||
| 161 | 27 | 2 | int git_reference_remove(git_repository *repo, const char *name) | |
| 162 | - | { | ||
| 163 | - | git_refdb *db; | ||
| 164 | - | int error; | ||
| 165 | - | |||
| 166 | 27 | 2,3 | if ((error = git_repository_refdb__weakptr(&db, repo)) < 0) | |
| 167 | ##### | 4 | return error; | |
| 168 | - | |||
| 169 | 27 | 5 | return git_refdb_delete(db, name, NULL, NULL); | |
| 170 | - | } | ||
| 171 | - | |||
| 172 | 13011 | 2 | int git_reference_lookup(git_reference **ref_out, | |
| 173 | - | git_repository *repo, const char *name) | ||
| 174 | - | { | ||
| 175 | 13011 | 2 | return git_reference_lookup_resolved(ref_out, repo, name, 0); | |
| 176 | - | } | ||
| 177 | - | |||
| 178 | 5749 | 2 | int git_reference_name_to_id( | |
| 179 | - | git_oid *out, git_repository *repo, const char *name) | ||
| 180 | - | { | ||
| 181 | - | int error; | ||
| 182 | - | git_reference *ref; | ||
| 183 | - | |||
| 184 | 5749 | 2,3 | if ((error = git_reference_lookup_resolved(&ref, repo, name, -1)) < 0) | |
| 185 | 2958 | 4 | return error; | |
| 186 | - | |||
| 187 | 2791 | 5,6 | git_oid_cpy(out, git_reference_target(ref)); | |
| 188 | 2791 | 7 | git_reference_free(ref); | |
| 189 | 2791 | 8 | return 0; | |
| 190 | - | } | ||
| 191 | - | |||
| 192 | ![]() |
33946 | 2 | static int reference_normalize_for_repo( |
| 193 | - | git_refname_t out, | ||
| 194 | - | git_repository *repo, | ||
| 195 | - | const char *name, | ||
| 196 | - | bool validate) | ||
| 197 | - | { | ||
| 198 | - | int precompose; | ||
| 199 | 33946 | 2 | unsigned int flags = GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL; | |
| 200 | - | |||
| 201 | 33946 | 2-4 | if (!git_repository__configmap_lookup(&precompose, repo, GIT_CONFIGMAP_PRECOMPOSE) && | |
| 202 | - | precompose) | ||
| 203 | 1025 | 5 | flags |= GIT_REFERENCE_FORMAT__PRECOMPOSE_UNICODE; | |
| 204 | - | |||
| 205 | 33946 | 6 | if (!validate) | |
| 206 | 1 | 7 | flags |= GIT_REFERENCE_FORMAT__VALIDATION_DISABLE; | |
| 207 | - | |||
| 208 | 33946 | 8 | return git_reference_normalize_name(out, GIT_REFNAME_MAX, name, flags); | |
| 209 | - | } | ||
| 210 | - | |||
| 211 | ![]() |
31378 | 2 | int git_reference_lookup_resolved( |
| 212 | - | git_reference **ref_out, | ||
| 213 | - | git_repository *repo, | ||
| 214 | - | const char *name, | ||
| 215 | - | int max_nesting) | ||
| 216 | - | { | ||
| 217 | - | git_refname_t scan_name; | ||
| 218 | - | git_reference_t scan_type; | ||
| 219 | 31378 | 2 | int error = 0, nesting; | |
| 220 | 31378 | 2 | git_reference *ref = NULL; | |
| 221 | - | git_refdb *refdb; | ||
| 222 | - | |||
| 223 | 31378 | 2-5 | assert(ref_out && repo && name); | |
| 224 | - | |||
| 225 | 31378 | 6 | *ref_out = NULL; | |
| 226 | - | |||
| 227 | 31378 | 6 | if (max_nesting > MAX_NESTING_LEVEL) | |
| 228 | ##### | 7 | max_nesting = MAX_NESTING_LEVEL; | |
| 229 | 31378 | 8 | else if (max_nesting < 0) | |
| 230 | 18268 | 9 | max_nesting = DEFAULT_NESTING_LEVEL; | |
| 231 | - | |||
| 232 | 31378 | 10 | scan_type = GIT_REFERENCE_SYMBOLIC; | |
| 233 | - | |||
| 234 | 31378 | 10,11 | if ((error = reference_normalize_for_repo(scan_name, repo, name, true)) < 0) | |
| 235 | 12 | 12 | return error; | |
| 236 | - | |||
| 237 | 31365 | 13,14 | if ((error = git_repository_refdb__weakptr(&refdb, repo)) < 0) | |
| 238 | ##### | 15 | return error; | |
| 239 | - | |||
| 240 | 52011 | 16,23 | for (nesting = max_nesting; | |
| 241 | 39711 | 24 | nesting >= 0 && scan_type == GIT_REFERENCE_SYMBOLIC; | |
| 242 | 20646 | 22 | nesting--) | |
| 243 | - | { | ||
| 244 | 32654 | 17 | if (nesting != max_nesting) { | |
| 245 | 1289 | 18 | strncpy(scan_name, ref->target.symbolic, sizeof(scan_name)); | |
| 246 | 1289 | 18 | git_reference_free(ref); | |
| 247 | - | } | ||
| 248 | - | |||
| 249 | 32655 | 19,20 | if ((error = git_refdb_lookup(&ref, refdb, scan_name)) < 0) | |
| 250 | 12009 | 21 | return error; | |
| 251 | - | |||
| 252 | 20646 | 22 | scan_type = ref->type; | |
| 253 | - | } | ||
| 254 | - | |||
| 255 | 19357 | 25,26 | if (scan_type != GIT_REFERENCE_DIRECT && max_nesting != 0) { | |
| 256 | ##### | 27 | git_error_set(GIT_ERROR_REFERENCE, | |
| 257 | - | "cannot resolve reference (>%u levels deep)", max_nesting); | ||
| 258 | ##### | 28 | git_reference_free(ref); | |
| 259 | ##### | 29 | return -1; | |
| 260 | - | } | ||
| 261 | - | |||
| 262 | 19357 | 30 | *ref_out = ref; | |
| 263 | 19357 | 30 | return 0; | |
| 264 | - | } | ||
| 265 | - | |||
| 266 | ![]() |
110 | 2 | int git_reference__read_head( |
| 267 | - | git_reference **out, | ||
| 268 | - | git_repository *repo, | ||
| 269 | - | const char *path) | ||
| 270 | - | { | ||
| 271 | 110 | 2 | git_buf reference = GIT_BUF_INIT; | |
| 272 | 110 | 2 | char *name = NULL; | |
| 273 | - | int error; | ||
| 274 | - | |||
| 275 | 110 | 2,3 | if ((error = git_futils_readbuffer(&reference, path)) < 0) | |
| 276 | 2 | 4 | goto out; | |
| 277 | 108 | 5 | git_buf_rtrim(&reference); | |
| 278 | - | |||
| 279 | 108 | 6 | if (git__strncmp(reference.ptr, GIT_SYMREF, strlen(GIT_SYMREF)) == 0) { | |
| 280 | 106 | 7 | git_buf_consume(&reference, reference.ptr + strlen(GIT_SYMREF)); | |
| 281 | - | |||
| 282 | 106 | 8 | name = git_path_basename(path); | |
| 283 | - | |||
| 284 | 106 | 9,10 | if ((*out = git_reference__alloc_symbolic(name, reference.ptr)) == NULL) { | |
| 285 | ##### | 11 | error = -1; | |
| 286 | ##### | 11 | goto out; | |
| 287 | - | } | ||
| 288 | - | } else { | ||
| 289 | 2 | 12,13 | if ((error = git_reference_lookup(out, repo, reference.ptr)) < 0) | |
| 290 | 2 | 14 | goto out; | |
| 291 | - | } | ||
| 292 | - | |||
| 293 | - | out: | ||
| 294 | 110 | 15 | git__free(name); | |
| 295 | 110 | 16 | git_buf_dispose(&reference); | |
| 296 | - | |||
| 297 | 110 | 17 | return error; | |
| 298 | - | } | ||
| 299 | - | |||
| 300 | ![]() |
1689 | 2 | int git_reference_dwim(git_reference **out, git_repository *repo, const char *refname) |
| 301 | - | { | ||
| 302 | 1689 | 2 | int error = 0, i; | |
| 303 | 1689 | 2 | bool fallbackmode = true, foundvalid = false; | |
| 304 | - | git_reference *ref; | ||
| 305 | 1689 | 2 | git_buf refnamebuf = GIT_BUF_INIT, name = GIT_BUF_INIT; | |
| 306 | - | |||
| 307 | - | static const char* formatters[] = { | ||
| 308 | - | "%s", | ||
| 309 | - | GIT_REFS_DIR "%s", | ||
| 310 | - | GIT_REFS_TAGS_DIR "%s", | ||
| 311 | - | GIT_REFS_HEADS_DIR "%s", | ||
| 312 | - | GIT_REFS_REMOTES_DIR "%s", | ||
| 313 | - | GIT_REFS_REMOTES_DIR "%s/" GIT_HEAD_FILE, | ||
| 314 | - | NULL | ||
| 315 | - | }; | ||
| 316 | - | |||
| 317 | 1689 | 2 | if (*refname) | |
| 318 | 1682 | 3 | git_buf_puts(&name, refname); | |
| 319 | - | else { | ||
| 320 | 7 | 4 | git_buf_puts(&name, GIT_HEAD_FILE); | |
| 321 | 7 | 5 | fallbackmode = false; | |
| 322 | - | } | ||
| 323 | - | |||
| 324 | 10180 | 6,22-25 | for (i = 0; formatters[i] && (fallbackmode || i == 0); i++) { | |
| 325 | - | |||
| 326 | 8819 | 7 | git_buf_clear(&refnamebuf); | |
| 327 | - | |||
| 328 | 8819 | 8-10 | if ((error = git_buf_printf(&refnamebuf, formatters[i], git_buf_cstr(&name))) < 0) | |
| 329 | ##### | 11 | goto cleanup; | |
| 330 | - | |||
| 331 | 8819 | 12-14 | if (!git_reference_is_valid_name(git_buf_cstr(&refnamebuf))) { | |
| 332 | 396 | 15 | error = GIT_EINVALIDSPEC; | |
| 333 | 396 | 15 | continue; | |
| 334 | - | } | ||
| 335 | 8423 | 16 | foundvalid = true; | |
| 336 | - | |||
| 337 | 8423 | 16,17 | error = git_reference_lookup_resolved(&ref, repo, git_buf_cstr(&refnamebuf), -1); | |
| 338 | - | |||
| 339 | 8423 | 18 | if (!error) { | |
| 340 | 328 | 19 | *out = ref; | |
| 341 | 328 | 19 | error = 0; | |
| 342 | 328 | 19 | goto cleanup; | |
| 343 | - | } | ||
| 344 | - | |||
| 345 | 8095 | 20 | if (error != GIT_ENOTFOUND) | |
| 346 | ##### | 21 | goto cleanup; | |
| 347 | - | } | ||
| 348 | - | |||
| 349 | - | cleanup: | ||
| 350 | 1689 | 26,27 | if (error && !foundvalid) { | |
| 351 | - | /* never found a valid reference name */ | ||
| 352 | 3 | 28,29 | git_error_set(GIT_ERROR_REFERENCE, | |
| 353 | - | "could not use '%s' as valid reference name", git_buf_cstr(&name)); | ||
| 354 | - | } | ||
| 355 | - | |||
| 356 | 1689 | 30 | if (error == GIT_ENOTFOUND) | |
| 357 | 1358 | 31 | git_error_set(GIT_ERROR_REFERENCE, "no reference found for shorthand '%s'", refname); | |
| 358 | - | |||
| 359 | 1689 | 32 | git_buf_dispose(&name); | |
| 360 | 1689 | 33 | git_buf_dispose(&refnamebuf); | |
| 361 | 1689 | 34 | return error; | |
| 362 | - | } | ||
| 363 | - | |||
| 364 | - | /** | ||
| 365 | - | * Getters | ||
| 366 | - | */ | ||
| 367 | 12254 | 2 | git_reference_t git_reference_type(const git_reference *ref) | |
| 368 | - | { | ||
| 369 | 12254 | 2,3 | assert(ref); | |
| 370 | 12254 | 4 | return ref->type; | |
| 371 | - | } | ||
| 372 | - | |||
| 373 | 2089 | 2 | const char *git_reference_name(const git_reference *ref) | |
| 374 | - | { | ||
| 375 | 2089 | 2,3 | assert(ref); | |
| 376 | 2089 | 4 | return ref->name; | |
| 377 | - | } | ||
| 378 | - | |||
| 379 | 4395 | 2 | git_repository *git_reference_owner(const git_reference *ref) | |
| 380 | - | { | ||
| 381 | 4395 | 2,3 | assert(ref); | |
| 382 | 4395 | 4 | return ref->db->repo; | |
| 383 | - | } | ||
| 384 | - | |||
| 385 | 6901 | 2 | const git_oid *git_reference_target(const git_reference *ref) | |
| 386 | - | { | ||
| 387 | 6901 | 2,3 | assert(ref); | |
| 388 | - | |||
| 389 | 6901 | 4 | if (ref->type != GIT_REFERENCE_DIRECT) | |
| 390 | 2 | 5 | return NULL; | |
| 391 | - | |||
| 392 | 6899 | 6 | return &ref->target.oid; | |
| 393 | - | } | ||
| 394 | - | |||
| 395 | ![]() |
##### | 2 | const git_oid *git_reference_target_peel(const git_reference *ref) |
| 396 | - | { | ||
| 397 | ##### | 2,3 | assert(ref); | |
| 398 | - | |||
| 399 | ##### | 4-6 | if (ref->type != GIT_REFERENCE_DIRECT || git_oid_is_zero(&ref->peel)) | |
| 400 | ##### | 7 | return NULL; | |
| 401 | - | |||
| 402 | ##### | 8 | return &ref->peel; | |
| 403 | - | } | ||
| 404 | - | |||
| 405 | 6139 | 2 | const char *git_reference_symbolic_target(const git_reference *ref) | |
| 406 | - | { | ||
| 407 | 6139 | 2,3 | assert(ref); | |
| 408 | - | |||
| 409 | 6139 | 4 | if (ref->type != GIT_REFERENCE_SYMBOLIC) | |
| 410 | ##### | 5 | return NULL; | |
| 411 | - | |||
| 412 | 6139 | 6 | return ref->target.symbolic; | |
| 413 | - | } | ||
| 414 | - | |||
| 415 | ![]() |
2246 | 2 | static int reference__create( |
| 416 | - | git_reference **ref_out, | ||
| 417 | - | git_repository *repo, | ||
| 418 | - | const char *name, | ||
| 419 | - | const git_oid *oid, | ||
| 420 | - | const char *symbolic, | ||
| 421 | - | int force, | ||
| 422 | - | const git_signature *signature, | ||
| 423 | - | const char *log_message, | ||
| 424 | - | const git_oid *old_id, | ||
| 425 | - | const char *old_target) | ||
| 426 | - | { | ||
| 427 | - | git_refname_t normalized; | ||
| 428 | - | git_refdb *refdb; | ||
| 429 | 2246 | 2 | git_reference *ref = NULL; | |
| 430 | 2246 | 2 | int error = 0; | |
| 431 | - | |||
| 432 | 2246 | 2-4 | assert(repo && name); | |
| 433 | 2246 | 5-7 | assert(symbolic || signature); | |
| 434 | - | |||
| 435 | 2246 | 8 | if (ref_out) | |
| 436 | 2235 | 9 | *ref_out = NULL; | |
| 437 | - | |||
| 438 | 2246 | 10 | error = reference_normalize_for_repo(normalized, repo, name, true); | |
| 439 | 2246 | 11 | if (error < 0) | |
| 440 | 17 | 12 | return error; | |
| 441 | - | |||
| 442 | 2229 | 13 | error = git_repository_refdb__weakptr(&refdb, repo); | |
| 443 | 2229 | 14 | if (error < 0) | |
| 444 | ##### | 15 | return error; | |
| 445 | - | |||
| 446 | 2229 | 16 | if (oid != NULL) { | |
| 447 | 1952 | 17,18 | assert(symbolic == NULL); | |
| 448 | - | |||
| 449 | 1952 | 19,20 | if (!git_object__is_valid(repo, oid, GIT_OBJECT_ANY)) { | |
| 450 | 1 | 21 | git_error_set(GIT_ERROR_REFERENCE, | |
| 451 | - | "target OID for the reference doesn't exist on the repository"); | ||
| 452 | 1 | 22 | return -1; | |
| 453 | - | } | ||
| 454 | - | |||
| 455 | 1951 | 23 | ref = git_reference__alloc(normalized, oid, NULL); | |
| 456 | - | } else { | ||
| 457 | - | git_refname_t normalized_target; | ||
| 458 | - | |||
| 459 | 277 | 24 | error = reference_normalize_for_repo(normalized_target, repo, | |
| 460 | - | symbolic, git_reference__enable_symbolic_ref_target_validation); | ||
| 461 | - | |||
| 462 | 277 | 25 | if (error < 0) | |
| 463 | 2 | 26 | return error; | |
| 464 | - | |||
| 465 | 275 | 27,28 | ref = git_reference__alloc_symbolic(normalized, normalized_target); | |
| 466 | - | } | ||
| 467 | - | |||
| 468 | 2226 | 29,30 | GIT_ERROR_CHECK_ALLOC(ref); | |
| 469 | - | |||
| 470 | 2226 | 31,32 | if ((error = git_refdb_write(refdb, ref, force, signature, log_message, old_id, old_target)) < 0) { | |
| 471 | 21 | 33 | git_reference_free(ref); | |
| 472 | 21 | 34 | return error; | |
| 473 | - | } | ||
| 474 | - | |||
| 475 | 2205 | 35 | if (ref_out == NULL) | |
| 476 | 9 | 36 | git_reference_free(ref); | |
| 477 | - | else | ||
| 478 | 2196 | 37 | *ref_out = ref; | |
| 479 | - | |||
| 480 | 2205 | 38 | return 0; | |
| 481 | - | } | ||
| 482 | - | |||
| 483 | 2175 | 2 | static int refs_configured_ident(git_signature **out, const git_repository *repo) | |
| 484 | - | { | ||
| 485 | 2175 | 2,3 | if (repo->ident_name && repo->ident_email) | |
| 486 | 89 | 4 | return git_signature_now(out, repo->ident_name, repo->ident_email); | |
| 487 | - | |||
| 488 | - | /* if not configured let us fall-through to the next method */ | ||
| 489 | 2086 | 5 | return -1; | |
| 490 | - | } | ||
| 491 | - | |||
| 492 | ![]() |
2175 | 2 | int git_reference__log_signature(git_signature **out, git_repository *repo) |
| 493 | - | { | ||
| 494 | - | int error; | ||
| 495 | - | git_signature *who; | ||
| 496 | - | |||
| 497 | 2175 | 2-5 | if(((error = refs_configured_ident(&who, repo)) < 0) && | |
| 498 | 2086 | 6,7 | ((error = git_signature_default(&who, repo)) < 0) && | |
| 499 | - | ((error = git_signature_now(&who, "unknown", "unknown")) < 0)) | ||
| 500 | ##### | 8 | return error; | |
| 501 | - | |||
| 502 | 2175 | 9 | *out = who; | |
| 503 | 2175 | 9 | return 0; | |
| 504 | - | } | ||
| 505 | - | |||
| 506 | 1645 | 2 | int git_reference_create_matching( | |
| 507 | - | git_reference **ref_out, | ||
| 508 | - | git_repository *repo, | ||
| 509 | - | const char *name, | ||
| 510 | - | const git_oid *id, | ||
| 511 | - | int force, | ||
| 512 | - | const git_oid *old_id, | ||
| 513 | - | const char *log_message) | ||
| 514 | - | |||
| 515 | - | { | ||
| 516 | - | int error; | ||
| 517 | 1645 | 2 | git_signature *who = NULL; | |
| 518 | - | |||
| 519 | 1645 | 2,3 | assert(id); | |
| 520 | - | |||
| 521 | 1645 | 4,5 | if ((error = git_reference__log_signature(&who, repo)) < 0) | |
| 522 | ##### | 6 | return error; | |
| 523 | - | |||
| 524 | 1645 | 7 | error = reference__create( | |
| 525 | - | ref_out, repo, name, id, NULL, force, who, log_message, old_id, NULL); | ||
| 526 | - | |||
| 527 | 1645 | 8 | git_signature_free(who); | |
| 528 | 1645 | 9 | return error; | |
| 529 | - | } | ||
| 530 | - | |||
| 531 | 1632 | 2 | int git_reference_create( | |
| 532 | - | git_reference **ref_out, | ||
| 533 | - | git_repository *repo, | ||
| 534 | - | const char *name, | ||
| 535 | - | const git_oid *id, | ||
| 536 | - | int force, | ||
| 537 | - | const char *log_message) | ||
| 538 | - | { | ||
| 539 | 1632 | 2 | return git_reference_create_matching(ref_out, repo, name, id, force, NULL, log_message); | |
| 540 | - | } | ||
| 541 | - | |||
| 542 | 285 | 2 | int git_reference_symbolic_create_matching( | |
| 543 | - | git_reference **ref_out, | ||
| 544 | - | git_repository *repo, | ||
| 545 | - | const char *name, | ||
| 546 | - | const char *target, | ||
| 547 | - | int force, | ||
| 548 | - | const char *old_target, | ||
| 549 | - | const char *log_message) | ||
| 550 | - | { | ||
| 551 | - | int error; | ||
| 552 | 285 | 2 | git_signature *who = NULL; | |
| 553 | - | |||
| 554 | 285 | 2,3 | assert(target); | |
| 555 | - | |||
| 556 | 285 | 4,5 | if ((error = git_reference__log_signature(&who, repo)) < 0) | |
| 557 | ##### | 6 | return error; | |
| 558 | - | |||
| 559 | 285 | 7 | error = reference__create( | |
| 560 | - | ref_out, repo, name, NULL, target, force, who, log_message, NULL, old_target); | ||
| 561 | - | |||
| 562 | 285 | 8 | git_signature_free(who); | |
| 563 | 285 | 9 | return error; | |
| 564 | - | } | ||
| 565 | - | |||
| 566 | 274 | 2 | int git_reference_symbolic_create( | |
| 567 | - | git_reference **ref_out, | ||
| 568 | - | git_repository *repo, | ||
| 569 | - | const char *name, | ||
| 570 | - | const char *target, | ||
| 571 | - | int force, | ||
| 572 | - | const char *log_message) | ||
| 573 | - | { | ||
| 574 | 274 | 2 | return git_reference_symbolic_create_matching(ref_out, repo, name, target, force, NULL, log_message); | |
| 575 | - | } | ||
| 576 | - | |||
| 577 | 36 | 2 | static int ensure_is_an_updatable_direct_reference(git_reference *ref) | |
| 578 | - | { | ||
| 579 | 36 | 2 | if (ref->type == GIT_REFERENCE_DIRECT) | |
| 580 | 35 | 3 | return 0; | |
| 581 | - | |||
| 582 | 1 | 4 | git_error_set(GIT_ERROR_REFERENCE, "cannot set OID on symbolic reference"); | |
| 583 | 1 | 5 | return -1; | |
| 584 | - | } | ||
| 585 | - | |||
| 586 | ![]() |
5 | 2 | int git_reference_set_target( |
| 587 | - | git_reference **out, | ||
| 588 | - | git_reference *ref, | ||
| 589 | - | const git_oid *id, | ||
| 590 | - | const char *log_message) | ||
| 591 | - | { | ||
| 592 | - | int error; | ||
| 593 | - | git_repository *repo; | ||
| 594 | - | |||
| 595 | 5 | 2-5 | assert(out && ref && id); | |
| 596 | - | |||
| 597 | 5 | 6 | repo = ref->db->repo; | |
| 598 | - | |||
| 599 | 5 | 6,7 | if ((error = ensure_is_an_updatable_direct_reference(ref)) < 0) | |
| 600 | 1 | 8 | return error; | |
| 601 | - | |||
| 602 | 4 | 9 | return git_reference_create_matching(out, repo, ref->name, id, 1, &ref->target.oid, log_message); | |
| 603 | - | } | ||
| 604 | - | |||
| 605 | 9 | 2 | static int ensure_is_an_updatable_symbolic_reference(git_reference *ref) | |
| 606 | - | { | ||
| 607 | 9 | 2 | if (ref->type == GIT_REFERENCE_SYMBOLIC) | |
| 608 | 8 | 3 | return 0; | |
| 609 | - | |||
| 610 | 1 | 4 | git_error_set(GIT_ERROR_REFERENCE, "cannot set symbolic target on a direct reference"); | |
| 611 | 1 | 5 | return -1; | |
| 612 | - | } | ||
| 613 | - | |||
| 614 | ![]() |
9 | 2 | int git_reference_symbolic_set_target( |
| 615 | - | git_reference **out, | ||
| 616 | - | git_reference *ref, | ||
| 617 | - | const char *target, | ||
| 618 | - | const char *log_message) | ||
| 619 | - | { | ||
| 620 | - | int error; | ||
| 621 | - | |||
| 622 | 9 | 2-5 | assert(out && ref && target); | |
| 623 | - | |||
| 624 | 9 | 6,7 | if ((error = ensure_is_an_updatable_symbolic_reference(ref)) < 0) | |
| 625 | 1 | 8 | return error; | |
| 626 | - | |||
| 627 | 8 | 9 | return git_reference_symbolic_create_matching( | |
| 628 | 8 | 9 | out, ref->db->repo, ref->name, target, 1, ref->target.symbolic, log_message); | |
| 629 | - | } | ||
| 630 | - | |||
| 631 | - | typedef struct { | ||
| 632 | - | const char *old_name; | ||
| 633 | - | git_refname_t new_name; | ||
| 634 | - | } rename_cb_data; | ||
| 635 | - | |||
| 636 | ![]() |
40 | 2 | static int update_wt_heads(git_repository *repo, const char *path, void *payload) |
| 637 | - | { | ||
| 638 | 40 | 2 | rename_cb_data *data = (rename_cb_data *) payload; | |
| 639 | 40 | 2 | git_reference *head = NULL; | |
| 640 | 40 | 2 | char *gitdir = NULL; | |
| 641 | - | int error; | ||
| 642 | - | |||
| 643 | 40 | 2,3 | if ((error = git_reference__read_head(&head, repo, path)) < 0) { | |
| 644 | ##### | 4 | git_error_set(GIT_ERROR_REFERENCE, "could not read HEAD when renaming references"); | |
| 645 | ##### | 5 | goto out; | |
| 646 | - | } | ||
| 647 | - | |||
| 648 | 40 | 6,7 | if ((gitdir = git_path_dirname(path)) == NULL) { | |
| 649 | ##### | 8 | error = -1; | |
| 650 | ##### | 8 | goto out; | |
| 651 | - | } | ||
| 652 | - | |||
| 653 | 40 | 9-11 | if (git_reference_type(head) != GIT_REFERENCE_SYMBOLIC || | |
| 654 | 40 | 11 | git__strcmp(head->target.symbolic, data->old_name) != 0) { | |
| 655 | 39 | 12 | error = 0; | |
| 656 | 39 | 12 | goto out; | |
| 657 | - | } | ||
| 658 | - | |||
| 659 | - | /* Update HEAD it was pointing to the reference being renamed */ | ||
| 660 | 1 | 13,14 | if ((error = git_repository_create_head(gitdir, data->new_name)) < 0) { | |
| 661 | ##### | 15 | git_error_set(GIT_ERROR_REFERENCE, "failed to update HEAD after renaming reference"); | |
| 662 | ##### | 16 | goto out; | |
| 663 | - | } | ||
| 664 | - | |||
| 665 | - | out: | ||
| 666 | 40 | 17 | git_reference_free(head); | |
| 667 | 40 | 18 | git__free(gitdir); | |
| 668 | - | |||
| 669 | 40 | 19 | return error; | |
| 670 | - | } | ||
| 671 | - | |||
| 672 | ![]() |
45 | 2 | static int reference__rename(git_reference **out, git_reference *ref, const char *new_name, int force, |
| 673 | - | const git_signature *signature, const char *message) | ||
| 674 | - | { | ||
| 675 | - | git_repository *repo; | ||
| 676 | - | git_refname_t normalized; | ||
| 677 | 45 | 2 | bool should_head_be_updated = false; | |
| 678 | 45 | 2 | int error = 0; | |
| 679 | - | |||
| 680 | 45 | 2-5 | assert(ref && new_name && signature); | |
| 681 | - | |||
| 682 | 45 | 6 | repo = git_reference_owner(ref); | |
| 683 | - | |||
| 684 | 45 | 7,8 | if ((error = reference_normalize_for_repo( | |
| 685 | - | normalized, repo, new_name, true)) < 0) | ||
| 686 | 3 | 9 | return error; | |
| 687 | - | |||
| 688 | - | /* Check if we have to update HEAD. */ | ||
| 689 | 42 | 10,11 | if ((error = git_branch_is_head(ref)) < 0) | |
| 690 | ##### | 12 | return error; | |
| 691 | - | |||
| 692 | 42 | 13 | should_head_be_updated = (error > 0); | |
| 693 | - | |||
| 694 | 42 | 13,14 | if ((error = git_refdb_rename(out, ref->db, ref->name, normalized, force, signature, message)) < 0) | |
| 695 | 5 | 15 | return error; | |
| 696 | - | |||
| 697 | - | /* Update HEAD if it was pointing to the reference being renamed */ | ||
| 698 | 37 | 16 | if (should_head_be_updated) { | |
| 699 | 6 | 17 | error = git_repository_set_head(ref->db->repo, normalized); | |
| 700 | - | } else { | ||
| 701 | - | rename_cb_data payload; | ||
| 702 | 31 | 18 | payload.old_name = ref->name; | |
| 703 | 31 | 18 | memcpy(&payload.new_name, &normalized, sizeof(normalized)); | |
| 704 | - | |||
| 705 | 31 | 18,19 | error = git_repository_foreach_head(repo, update_wt_heads, 0, &payload); | |
| 706 | - | } | ||
| 707 | - | |||
| 708 | 37 | 20 | return error; | |
| 709 | - | } | ||
| 710 | - | |||
| 711 | - | |||
| 712 | ![]() |
45 | 2 | int git_reference_rename( |
| 713 | - | git_reference **out, | ||
| 714 | - | git_reference *ref, | ||
| 715 | - | const char *new_name, | ||
| 716 | - | int force, | ||
| 717 | - | const char *log_message) | ||
| 718 | - | { | ||
| 719 | - | git_signature *who; | ||
| 720 | - | int error; | ||
| 721 | - | |||
| 722 | 45 | 2-4 | assert(out && ref); | |
| 723 | - | |||
| 724 | 45 | 5,6 | if ((error = git_reference__log_signature(&who, ref->db->repo)) < 0) | |
| 725 | ##### | 7 | return error; | |
| 726 | - | |||
| 727 | 45 | 8 | error = reference__rename(out, ref, new_name, force, who, log_message); | |
| 728 | 45 | 9 | git_signature_free(who); | |
| 729 | - | |||
| 730 | 45 | 10 | return error; | |
| 731 | - | } | ||
| 732 | - | |||
| 733 | 2051 | 2 | int git_reference_resolve(git_reference **ref_out, const git_reference *ref) | |
| 734 | - | { | ||
| 735 | 2051 | 2,3 | switch (git_reference_type(ref)) { | |
| 736 | - | case GIT_REFERENCE_DIRECT: | ||
| 737 | 1767 | 4 | return git_reference_lookup(ref_out, ref->db->repo, ref->name); | |
| 738 | - | |||
| 739 | - | case GIT_REFERENCE_SYMBOLIC: | ||
| 740 | 284 | 5 | return git_reference_lookup_resolved(ref_out, ref->db->repo, ref->target.symbolic, -1); | |
| 741 | - | |||
| 742 | - | default: | ||
| 743 | ##### | 6 | git_error_set(GIT_ERROR_REFERENCE, "invalid reference"); | |
| 744 | ##### | 7 | return -1; | |
| 745 | - | } | ||
| 746 | - | } | ||
| 747 | - | |||
| 748 | ![]() |
40 | 2 | int git_reference_foreach( |
| 749 | - | git_repository *repo, | ||
| 750 | - | git_reference_foreach_cb callback, | ||
| 751 | - | void *payload) | ||
| 752 | - | { | ||
| 753 | - | git_reference_iterator *iter; | ||
| 754 | - | git_reference *ref; | ||
| 755 | - | int error; | ||
| 756 | - | |||
| 757 | 40 | 2,3 | if ((error = git_reference_iterator_new(&iter, repo)) < 0) | |
| 758 | ##### | 4 | return error; | |
| 759 | - | |||
| 760 | 115 | 5,10,11 | while (!(error = git_reference_next(&ref, iter))) { | |
| 761 | 76 | 6,7 | if ((error = callback(ref, payload)) != 0) { | |
| 762 | 1 | 8 | git_error_set_after_callback(error); | |
| 763 | 1 | 9 | break; | |
| 764 | - | } | ||
| 765 | - | } | ||
| 766 | - | |||
| 767 | 40 | 12 | if (error == GIT_ITEROVER) | |
| 768 | 39 | 13 | error = 0; | |
| 769 | - | |||
| 770 | 40 | 14 | git_reference_iterator_free(iter); | |
| 771 | 40 | 15 | return error; | |
| 772 | - | } | ||
| 773 | - | |||
| 774 | ![]() |
341 | 2 | int git_reference_foreach_name( |
| 775 | - | git_repository *repo, | ||
| 776 | - | git_reference_foreach_name_cb callback, | ||
| 777 | - | void *payload) | ||
| 778 | - | { | ||
| 779 | - | git_reference_iterator *iter; | ||
| 780 | - | const char *refname; | ||
| 781 | - | int error; | ||
| 782 | - | |||
| 783 | 341 | 2,3 | if ((error = git_reference_iterator_new(&iter, repo)) < 0) | |
| 784 | ##### | 4 | return error; | |
| 785 | - | |||
| 786 | 4211 | 5,10,11 | while (!(error = git_reference_next_name(&refname, iter))) { | |
| 787 | 3873 | 6,7 | if ((error = callback(refname, payload)) != 0) { | |
| 788 | 3 | 8 | git_error_set_after_callback(error); | |
| 789 | 3 | 9 | break; | |
| 790 | - | } | ||
| 791 | - | } | ||
| 792 | - | |||
| 793 | 341 | 12 | if (error == GIT_ITEROVER) | |
| 794 | 338 | 13 | error = 0; | |
| 795 | - | |||
| 796 | 341 | 14 | git_reference_iterator_free(iter); | |
| 797 | 341 | 15 | return error; | |
| 798 | - | } | ||
| 799 | - | |||
| 800 | ![]() |
6 | 2 | int git_reference_foreach_glob( |
| 801 | - | git_repository *repo, | ||
| 802 | - | const char *glob, | ||
| 803 | - | git_reference_foreach_name_cb callback, | ||
| 804 | - | void *payload) | ||
| 805 | - | { | ||
| 806 | - | git_reference_iterator *iter; | ||
| 807 | - | const char *refname; | ||
| 808 | - | int error; | ||
| 809 | - | |||
| 810 | 6 | 2,3 | if ((error = git_reference_iterator_glob_new(&iter, repo, glob)) < 0) | |
| 811 | ##### | 4 | return error; | |
| 812 | - | |||
| 813 | 57 | 5,10,11 | while (!(error = git_reference_next_name(&refname, iter))) { | |
| 814 | 52 | 6,7 | if ((error = callback(refname, payload)) != 0) { | |
| 815 | 1 | 8 | git_error_set_after_callback(error); | |
| 816 | 1 | 9 | break; | |
| 817 | - | } | ||
| 818 | - | } | ||
| 819 | - | |||
| 820 | 6 | 12 | if (error == GIT_ITEROVER) | |
| 821 | 5 | 13 | error = 0; | |
| 822 | - | |||
| 823 | 6 | 14 | git_reference_iterator_free(iter); | |
| 824 | 6 | 15 | return error; | |
| 825 | - | } | ||
| 826 | - | |||
| 827 | 427 | 2 | int git_reference_iterator_new(git_reference_iterator **out, git_repository *repo) | |
| 828 | - | { | ||
| 829 | - | git_refdb *refdb; | ||
| 830 | - | |||
| 831 | 427 | 2,3 | if (git_repository_refdb__weakptr(&refdb, repo) < 0) | |
| 832 | ##### | 4 | return -1; | |
| 833 | - | |||
| 834 | 427 | 5 | return git_refdb_iterator(out, refdb, NULL); | |
| 835 | - | } | ||
| 836 | - | |||
| 837 | 61 | 2 | int git_reference_iterator_glob_new( | |
| 838 | - | git_reference_iterator **out, git_repository *repo, const char *glob) | ||
| 839 | - | { | ||
| 840 | - | git_refdb *refdb; | ||
| 841 | - | |||
| 842 | 61 | 2,3 | if (git_repository_refdb__weakptr(&refdb, repo) < 0) | |
| 843 | ##### | 4 | return -1; | |
| 844 | - | |||
| 845 | 61 | 5 | return git_refdb_iterator(out, refdb, glob); | |
| 846 | - | } | ||
| 847 | - | |||
| 848 | 3097 | 2 | int git_reference_next(git_reference **out, git_reference_iterator *iter) | |
| 849 | - | { | ||
| 850 | 3097 | 2 | return git_refdb_iterator_next(out, iter); | |
| 851 | - | } | ||
| 852 | - | |||
| 853 | 4400 | 2 | int git_reference_next_name(const char **out, git_reference_iterator *iter) | |
| 854 | - | { | ||
| 855 | 4400 | 2 | return git_refdb_iterator_next_name(out, iter); | |
| 856 | - | } | ||
| 857 | - | |||
| 858 | 488 | 2 | void git_reference_iterator_free(git_reference_iterator *iter) | |
| 859 | - | { | ||
| 860 | 488 | 2 | if (iter == NULL) | |
| 861 | 488 | 3,5 | return; | |
| 862 | - | |||
| 863 | 488 | 4 | git_refdb_iterator_free(iter); | |
| 864 | - | } | ||
| 865 | - | |||
| 866 | 2331 | 2 | static int cb__reflist_add(const char *ref, void *data) | |
| 867 | - | { | ||
| 868 | 2331 | 2 | char *name = git__strdup(ref); | |
| 869 | 2331 | 3,4 | GIT_ERROR_CHECK_ALLOC(name); | |
| 870 | 2331 | 5 | return git_vector_insert((git_vector *)data, name); | |
| 871 | - | } | ||
| 872 | - | |||
| 873 | ![]() |
136 | 2 | int git_reference_list( |
| 874 | - | git_strarray *array, | ||
| 875 | - | git_repository *repo) | ||
| 876 | - | { | ||
| 877 | - | git_vector ref_list; | ||
| 878 | - | |||
| 879 | 136 | 2-4 | assert(array && repo); | |
| 880 | - | |||
| 881 | 136 | 5 | array->strings = NULL; | |
| 882 | 136 | 5 | array->count = 0; | |
| 883 | - | |||
| 884 | 136 | 5,6 | if (git_vector_init(&ref_list, 8, NULL) < 0) | |
| 885 | ##### | 7 | return -1; | |
| 886 | - | |||
| 887 | 136 | 8,9 | if (git_reference_foreach_name( | |
| 888 | - | repo, &cb__reflist_add, (void *)&ref_list) < 0) { | ||
| 889 | ##### | 10 | git_vector_free(&ref_list); | |
| 890 | ##### | 11 | return -1; | |
| 891 | - | } | ||
| 892 | - | |||
| 893 | 136 | 12 | array->strings = (char **)git_vector_detach(&array->count, NULL, &ref_list); | |
| 894 | - | |||
| 895 | 136 | 13 | return 0; | |
| 896 | - | } | ||
| 897 | - | |||
| 898 | 880764 | 2 | static int is_valid_ref_char(char ch) | |
| 899 | - | { | ||
| 900 | 880764 | 2 | if ((unsigned) ch <= ' ') | |
| 901 | 66 | 3 | return 0; | |
| 902 | - | |||
| 903 | 880698 | 4 | switch (ch) { | |
| 904 | - | case '~': | ||
| 905 | - | case '^': | ||
| 906 | - | case ':': | ||
| 907 | - | case '\\': | ||
| 908 | - | case '?': | ||
| 909 | - | case '[': | ||
| 910 | 1107 | 5 | return 0; | |
| 911 | - | default: | ||
| 912 | 879591 | 6 | return 1; | |
| 913 | - | } | ||
| 914 | - | } | ||
| 915 | - | |||
| 916 | ![]() |
162063 | 2 | static int ensure_segment_validity(const char *name, char may_contain_glob) |
| 917 | - | { | ||
| 918 | 162063 | 2 | const char *current = name; | |
| 919 | 162063 | 2 | char prev = '\0'; | |
| 920 | 162063 | 2 | const int lock_len = (int)strlen(GIT_FILELOCK_EXTENSION); | |
| 921 | - | int segment_len; | ||
| 922 | - | |||
| 923 | 162063 | 2 | if (*current == '.') | |
| 924 | 13 | 3 | return -1; /* Refname starts with "." */ | |
| 925 | - | |||
| 926 | 879555 | 4,20 | for (current = name; ; current++) { | |
| 927 | 1041605 | 5,6 | if (*current == '\0' || *current == '/') | |
| 928 | - | break; | ||
| 929 | - | |||
| 930 | 880764 | 7,8 | if (!is_valid_ref_char(*current)) | |
| 931 | 1173 | 9 | return -1; /* Illegal character in refname */ | |
| 932 | - | |||
| 933 | 879590 | 10,11 | if (prev == '.' && *current == '.') | |
| 934 | 2 | 12 | return -1; /* Refname contains ".." */ | |
| 935 | - | |||
| 936 | 879588 | 13,14 | if (prev == '@' && *current == '{') | |
| 937 | 19 | 15 | return -1; /* Refname contains "@{" */ | |
| 938 | - | |||
| 939 | 879569 | 16 | if (*current == '*') { | |
| 940 | 1952 | 17 | if (!may_contain_glob) | |
| 941 | 14 | 18 | return -1; | |
| 942 | 1938 | 19 | may_contain_glob = 0; | |
| 943 | - | } | ||
| 944 | - | |||
| 945 | 879555 | 20 | prev = *current; | |
| 946 | 879555 | 20 | } | |
| 947 | - | |||
| 948 | 160841 | 21 | segment_len = (int)(current - name); | |
| 949 | - | |||
| 950 | - | /* A refname component can not end with ".lock" */ | ||
| 951 | 160841 | 21,22 | if (segment_len >= lock_len && | |
| 952 | 70476 | 22 | !memcmp(current - lock_len, GIT_FILELOCK_EXTENSION, lock_len)) | |
| 953 | 6 | 23 | return -1; | |
| 954 | - | |||
| 955 | 160835 | 24 | return segment_len; | |
| 956 | - | } | ||
| 957 | - | |||
| 958 | ![]() |
51183 | 2 | static bool is_all_caps_and_underscore(const char *name, size_t len) |
| 959 | - | { | ||
| 960 | - | size_t i; | ||
| 961 | - | char c; | ||
| 962 | - | |||
| 963 | 51183 | 2-4 | assert(name && len > 0); | |
| 964 | - | |||
| 965 | 89857 | 5,10,11 | for (i = 0; i < len; i++) | |
| 966 | - | { | ||
| 967 | 80246 | 6 | c = name[i]; | |
| 968 | 80246 | 6-8 | if ((c < 'A' || c > 'Z') && c != '_') | |
| 969 | 41572 | 9 | return false; | |
| 970 | - | } | ||
| 971 | - | |||
| 972 | 9611 | 12,13 | if (*name == '_' || name[len - 1] == '_') | |
| 973 | 2 | 14 | return false; | |
| 974 | - | |||
| 975 | 9609 | 15 | return true; | |
| 976 | - | } | ||
| 977 | - | |||
| 978 | - | /* Inspired from https://github.com/git/git/blob/f06d47e7e0d9db709ee204ed13a8a7486149f494/refs.c#L36-100 */ | ||
| 979 | ![]() |
52523 | 2 | int git_reference__normalize_name( |
| 980 | - | git_buf *buf, | ||
| 981 | - | const char *name, | ||
| 982 | - | unsigned int flags) | ||
| 983 | - | { | ||
| 984 | - | const char *current; | ||
| 985 | 52523 | 2 | int segment_len, segments_count = 0, error = GIT_EINVALIDSPEC; | |
| 986 | - | unsigned int process_flags; | ||
| 987 | 52523 | 2 | bool normalize = (buf != NULL); | |
| 988 | 52523 | 2 | bool validate = (flags & GIT_REFERENCE_FORMAT__VALIDATION_DISABLE) == 0; | |
| 989 | - | |||
| 990 | - | #ifdef GIT_USE_ICONV | ||
| 991 | - | git_path_iconv_t ic = GIT_PATH_ICONV_INIT; | ||
| 992 | - | #endif | ||
| 993 | - | |||
| 994 | 52523 | 2,3 | assert(name); | |
| 995 | - | |||
| 996 | 52523 | 4 | process_flags = flags; | |
| 997 | 52523 | 4 | current = (char *)name; | |
| 998 | - | |||
| 999 | 52523 | 4,5 | if (validate && *current == '/') | |
| 1000 | 10 | 6 | goto cleanup; | |
| 1001 | - | |||
| 1002 | 52513 | 7 | if (normalize) | |
| 1003 | 34129 | 8 | git_buf_clear(buf); | |
| 1004 | - | |||
| 1005 | - | #ifdef GIT_USE_ICONV | ||
| 1006 | - | if ((flags & GIT_REFERENCE_FORMAT__PRECOMPOSE_UNICODE) != 0) { | ||
| 1007 | - | size_t namelen = strlen(current); | ||
| 1008 | - | if ((error = git_path_iconv_init_precompose(&ic)) < 0 || | ||
| 1009 | - | (error = git_path_iconv(&ic, ¤t, &namelen)) < 0) | ||
| 1010 | - | goto cleanup; | ||
| 1011 | - | error = GIT_EINVALIDSPEC; | ||
| 1012 | - | } | ||
| 1013 | - | #endif | ||
| 1014 | - | |||
| 1015 | 52513 | 9 | if (!validate) { | |
| 1016 | 1 | 10 | git_buf_sets(buf, current); | |
| 1017 | - | |||
| 1018 | 1 | 11-14 | error = git_buf_oom(buf) ? -1 : 0; | |
| 1019 | 1 | 15 | goto cleanup; | |
| 1020 | - | } | ||
| 1021 | - | |||
| 1022 | - | while (true) { | ||
| 1023 | 162064 | 16 | char may_contain_glob = process_flags & GIT_REFERENCE_FORMAT_REFSPEC_PATTERN; | |
| 1024 | - | |||
| 1025 | 162064 | 16 | segment_len = ensure_segment_validity(current, may_contain_glob); | |
| 1026 | 162066 | 17 | if (segment_len < 0) | |
| 1027 | 1227 | 18 | goto cleanup; | |
| 1028 | - | |||
| 1029 | 160839 | 19 | if (segment_len > 0) { | |
| 1030 | - | /* | ||
| 1031 | - | * There may only be one glob in a pattern, thus we reset | ||
| 1032 | - | * the pattern-flag in case the current segment has one. | ||
| 1033 | - | */ | ||
| 1034 | 160795 | 20 | if (memchr(current, '*', segment_len)) | |
| 1035 | 1936 | 21 | process_flags &= ~GIT_REFERENCE_FORMAT_REFSPEC_PATTERN; | |
| 1036 | - | |||
| 1037 | 160795 | 22 | if (normalize) { | |
| 1038 | 96875 | 23 | size_t cur_len = git_buf_len(buf); | |
| 1039 | - | |||
| 1040 | 96875 | 24,25 | git_buf_joinpath(buf, git_buf_cstr(buf), current); | |
| 1041 | 96876 | 26-29 | git_buf_truncate(buf, | |
| 1042 | 96876 | 26 | cur_len + segment_len + (segments_count ? 1 : 0)); | |
| 1043 | - | |||
| 1044 | 96873 | 30,31 | if (git_buf_oom(buf)) { | |
| 1045 | ##### | 32 | error = -1; | |
| 1046 | ##### | 32 | goto cleanup; | |
| 1047 | - | } | ||
| 1048 | - | } | ||
| 1049 | - | |||
| 1050 | 160793 | 33 | segments_count++; | |
| 1051 | - | } | ||
| 1052 | - | |||
| 1053 | - | /* No empty segment is allowed when not normalizing */ | ||
| 1054 | 160837 | 34,35 | if (segment_len == 0 && !normalize) | |
| 1055 | 12 | 36 | goto cleanup; | |
| 1056 | - | |||
| 1057 | 160825 | 37 | if (current[segment_len] == '\0') | |
| 1058 | 51273 | 38 | break; | |
| 1059 | - | |||
| 1060 | 109552 | 39 | current += segment_len + 1; | |
| 1061 | 109552 | 39 | } | |
| 1062 | - | |||
| 1063 | - | /* A refname can not be empty */ | ||
| 1064 | 51273 | 40,41 | if (segment_len == 0 && segments_count == 0) | |
| 1065 | 3 | 42 | goto cleanup; | |
| 1066 | - | |||
| 1067 | - | /* A refname can not end with "." */ | ||
| 1068 | 51270 | 43 | if (current[segment_len - 1] == '.') | |
| 1069 | 4 | 44 | goto cleanup; | |
| 1070 | - | |||
| 1071 | - | /* A refname can not end with "/" */ | ||
| 1072 | 51266 | 45 | if (current[segment_len - 1] == '/') | |
| 1073 | 3 | 46 | goto cleanup; | |
| 1074 | - | |||
| 1075 | 51263 | 47,48 | if ((segments_count == 1 ) && !(flags & GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL)) | |
| 1076 | 4 | 49 | goto cleanup; | |
| 1077 | - | |||
| 1078 | 51259 | 50,51 | if ((segments_count == 1 ) && | |
| 1079 | 10069 | 51,53 | !(flags & GIT_REFERENCE_FORMAT_REFSPEC_SHORTHAND) && | |
| 1080 | 9993 | 52,54 | !(is_all_caps_and_underscore(name, (size_t)segment_len) || | |
| 1081 | 386 | 54,55 | ((flags & GIT_REFERENCE_FORMAT_REFSPEC_PATTERN) && !strcmp("*", name)))) | |
| 1082 | - | goto cleanup; | ||
| 1083 | - | |||
| 1084 | 50874 | 56 | if ((segments_count > 1) | |
| 1085 | 41190 | 57,58 | && (is_all_caps_and_underscore(name, strchr(name, '/') - name))) | |
| 1086 | 2 | 59 | goto cleanup; | |
| 1087 | - | |||
| 1088 | 50871 | 60 | error = 0; | |
| 1089 | - | |||
| 1090 | - | cleanup: | ||
| 1091 | 52522 | 61 | if (error == GIT_EINVALIDSPEC) | |
| 1092 | 1650 | 62 | git_error_set( | |
| 1093 | - | GIT_ERROR_REFERENCE, | ||
| 1094 | - | "the given reference name '%s' is not valid", name); | ||
| 1095 | - | |||
| 1096 | 52522 | 63,64 | if (error && normalize) | |
| 1097 | 129 | 65 | git_buf_dispose(buf); | |
| 1098 | - | |||
| 1099 | - | #ifdef GIT_USE_ICONV | ||
| 1100 | - | git_path_iconv_clear(&ic); | ||
| 1101 | - | #endif | ||
| 1102 | - | |||
| 1103 | 52522 | 66 | return error; | |
| 1104 | - | } | ||
| 1105 | - | |||
| 1106 | 34098 | 2 | int git_reference_normalize_name( | |
| 1107 | - | char *buffer_out, | ||
| 1108 | - | size_t buffer_size, | ||
| 1109 | - | const char *name, | ||
| 1110 | - | unsigned int flags) | ||
| 1111 | - | { | ||
| 1112 | 34098 | 2 | git_buf buf = GIT_BUF_INIT; | |
| 1113 | - | int error; | ||
| 1114 | - | |||
| 1115 | 34098 | 2,3 | if ((error = git_reference__normalize_name(&buf, name, flags)) < 0) | |
| 1116 | 128 | 4 | goto cleanup; | |
| 1117 | - | |||
| 1118 | 33969 | 5,6 | if (git_buf_len(&buf) > buffer_size - 1) { | |
| 1119 | 1 | 7 | git_error_set( | |
| 1120 | - | GIT_ERROR_REFERENCE, | ||
| 1121 | - | "the provided buffer is too short to hold the normalization of '%s'", name); | ||
| 1122 | 1 | 8 | error = GIT_EBUFS; | |
| 1123 | 1 | 8 | goto cleanup; | |
| 1124 | - | } | ||
| 1125 | - | |||
| 1126 | 33968 | 9 | git_buf_copy_cstr(buffer_out, buffer_size, &buf); | |
| 1127 | - | |||
| 1128 | 33968 | 10 | error = 0; | |
| 1129 | - | |||
| 1130 | - | cleanup: | ||
| 1131 | 34097 | 11 | git_buf_dispose(&buf); | |
| 1132 | 34096 | 12 | return error; | |
| 1133 | - | } | ||
| 1134 | - | |||
| 1135 | - | #define GIT_REFERENCE_TYPEMASK (GIT_REFERENCE_DIRECT | GIT_REFERENCE_SYMBOLIC) | ||
| 1136 | - | |||
| 1137 | ![]() |
7 | 2 | int git_reference_cmp( |
| 1138 | - | const git_reference *ref1, | ||
| 1139 | - | const git_reference *ref2) | ||
| 1140 | - | { | ||
| 1141 | - | git_reference_t type1, type2; | ||
| 1142 | 7 | 2-4 | assert(ref1 && ref2); | |
| 1143 | - | |||
| 1144 | 7 | 5 | type1 = git_reference_type(ref1); | |
| 1145 | 7 | 6 | type2 = git_reference_type(ref2); | |
| 1146 | - | |||
| 1147 | - | /* let's put symbolic refs before OIDs */ | ||
| 1148 | 7 | 7 | if (type1 != type2) | |
| 1149 | 1 | 8-11 | return (type1 == GIT_REFERENCE_SYMBOLIC) ? -1 : 1; | |
| 1150 | - | |||
| 1151 | 6 | 12 | if (type1 == GIT_REFERENCE_SYMBOLIC) | |
| 1152 | 1 | 13 | return strcmp(ref1->target.symbolic, ref2->target.symbolic); | |
| 1153 | - | |||
| 1154 | 5 | 14 | return git_oid__cmp(&ref1->target.oid, &ref2->target.oid); | |
| 1155 | - | } | ||
| 1156 | - | |||
| 1157 | - | /** | ||
| 1158 | - | * Get the end of a chain of references. If the final one is not | ||
| 1159 | - | * found, we return the reference just before that. | ||
| 1160 | - | */ | ||
| 1161 | ![]() |
531 | 2 | static int get_terminal(git_reference **out, git_repository *repo, const char *ref_name, int nesting) |
| 1162 | - | { | ||
| 1163 | - | git_reference *ref; | ||
| 1164 | 531 | 2 | int error = 0; | |
| 1165 | - | |||
| 1166 | 531 | 2 | if (nesting > MAX_NESTING_LEVEL) { | |
| 1167 | ##### | 3 | git_error_set(GIT_ERROR_REFERENCE, "reference chain too deep (%d)", nesting); | |
| 1168 | ##### | 4 | return GIT_ENOTFOUND; | |
| 1169 | - | } | ||
| 1170 | - | |||
| 1171 | - | /* set to NULL to let the caller know that they're at the end of the chain */ | ||
| 1172 | 531 | 5,6 | if ((error = git_reference_lookup(&ref, repo, ref_name)) < 0) { | |
| 1173 | 64 | 7 | *out = NULL; | |
| 1174 | 64 | 7 | return error; | |
| 1175 | - | } | ||
| 1176 | - | |||
| 1177 | 467 | 8,9 | if (git_reference_type(ref) == GIT_REFERENCE_DIRECT) { | |
| 1178 | 221 | 10 | *out = ref; | |
| 1179 | 221 | 10 | error = 0; | |
| 1180 | - | } else { | ||
| 1181 | 246 | 11,12 | error = get_terminal(out, repo, git_reference_symbolic_target(ref), nesting + 1); | |
| 1182 | 246 | 13,14 | if (error == GIT_ENOTFOUND && !*out) | |
| 1183 | 62 | 15 | *out = ref; | |
| 1184 | - | else | ||
| 1185 | 184 | 16 | git_reference_free(ref); | |
| 1186 | - | } | ||
| 1187 | - | |||
| 1188 | 467 | 17 | return error; | |
| 1189 | - | } | ||
| 1190 | - | |||
| 1191 | - | /* | ||
| 1192 | - | * Starting with the reference given by `ref_name`, follows symbolic | ||
| 1193 | - | * references until a direct reference is found and updated the OID | ||
| 1194 | - | * on that direct reference to `oid`. | ||
| 1195 | - | */ | ||
| 1196 | ![]() |
285 | 2 | int git_reference__update_terminal( |
| 1197 | - | git_repository *repo, | ||
| 1198 | - | const char *ref_name, | ||
| 1199 | - | const git_oid *oid, | ||
| 1200 | - | const git_signature *sig, | ||
| 1201 | - | const char *log_message) | ||
| 1202 | - | { | ||
| 1203 | 285 | 2 | git_reference *ref = NULL, *ref2 = NULL; | |
| 1204 | 285 | 2 | git_signature *who = NULL; | |
| 1205 | - | const git_signature *to_use; | ||
| 1206 | 285 | 2 | int error = 0; | |
| 1207 | - | |||
| 1208 | 285 | 2-4 | if (!sig && (error = git_reference__log_signature(&who, repo)) < 0) | |
| 1209 | ##### | 5 | return error; | |
| 1210 | - | |||
| 1211 | 285 | 6-8 | to_use = sig ? sig : who; | |
| 1212 | 285 | 9 | error = get_terminal(&ref, repo, ref_name, 0); | |
| 1213 | - | |||
| 1214 | - | /* found a dangling symref */ | ||
| 1215 | 285 | 10,11 | if (error == GIT_ENOTFOUND && ref) { | |
| 1216 | 62 | 12-14 | assert(git_reference_type(ref) == GIT_REFERENCE_SYMBOLIC); | |
| 1217 | 62 | 15 | git_error_clear(); | |
| 1218 | 62 | 16 | error = reference__create(&ref2, repo, ref->target.symbolic, oid, NULL, 0, to_use, | |
| 1219 | - | log_message, NULL, NULL); | ||
| 1220 | 223 | 17 | } else if (error == GIT_ENOTFOUND) { | |
| 1221 | 2 | 18 | git_error_clear(); | |
| 1222 | 2 | 19 | error = reference__create(&ref2, repo, ref_name, oid, NULL, 0, to_use, | |
| 1223 | - | log_message, NULL, NULL); | ||
| 1224 | 221 | 20 | } else if (error == 0) { | |
| 1225 | 221 | 21-23 | assert(git_reference_type(ref) == GIT_REFERENCE_DIRECT); | |
| 1226 | 221 | 24 | error = reference__create(&ref2, repo, ref->name, oid, NULL, 1, to_use, | |
| 1227 | 221 | 24 | log_message, &ref->target.oid, NULL); | |
| 1228 | - | } | ||
| 1229 | - | |||
| 1230 | 285 | 25 | git_reference_free(ref2); | |
| 1231 | 285 | 26 | git_reference_free(ref); | |
| 1232 | 285 | 27 | git_signature_free(who); | |
| 1233 | 285 | 28 | return error; | |
| 1234 | - | } | ||
| 1235 | - | |||
| 1236 | 126 | 2 | static const char *commit_type(const git_commit *commit) | |
| 1237 | - | { | ||
| 1238 | 126 | 2 | unsigned int count = git_commit_parentcount(commit); | |
| 1239 | - | |||
| 1240 | 126 | 3 | if (count >= 2) | |
| 1241 | 1 | 4 | return " (merge)"; | |
| 1242 | 125 | 5 | else if (count == 0) | |
| 1243 | 63 | 6 | return " (initial)"; | |
| 1244 | - | else | ||
| 1245 | 62 | 7 | return ""; | |
| 1246 | - | } | ||
| 1247 | - | |||
| 1248 | ![]() |
126 | 2 | int git_reference__update_for_commit( |
| 1249 | - | git_repository *repo, | ||
| 1250 | - | git_reference *ref, | ||
| 1251 | - | const char *ref_name, | ||
| 1252 | - | const git_oid *id, | ||
| 1253 | - | const char *operation) | ||
| 1254 | - | { | ||
| 1255 | 126 | 2 | git_reference *ref_new = NULL; | |
| 1256 | 126 | 2 | git_commit *commit = NULL; | |
| 1257 | 126 | 2 | git_buf reflog_msg = GIT_BUF_INIT; | |
| 1258 | - | const git_signature *who; | ||
| 1259 | - | int error; | ||
| 1260 | - | |||
| 1261 | 126 | 2,3,9,10 | if ((error = git_commit_lookup(&commit, repo, id)) < 0 || | |
| 1262 | 126 | 4-8 | (error = git_buf_printf(&reflog_msg, "%s%s: %s", | |
| 1263 | - | operation ? operation : "commit", | ||
| 1264 | - | commit_type(commit), | ||
| 1265 | - | git_commit_summary(commit))) < 0) | ||
| 1266 | - | goto done; | ||
| 1267 | - | |||
| 1268 | 126 | 11 | who = git_commit_committer(commit); | |
| 1269 | - | |||
| 1270 | 126 | 12 | if (ref) { | |
| 1271 | 31 | 13,14 | if ((error = ensure_is_an_updatable_direct_reference(ref)) < 0) | |
| 1272 | ##### | 15 | return error; | |
| 1273 | - | |||
| 1274 | 31 | 16,17 | error = reference__create(&ref_new, repo, ref->name, id, NULL, 1, who, | |
| 1275 | 31 | 16 | git_buf_cstr(&reflog_msg), &ref->target.oid, NULL); | |
| 1276 | - | } | ||
| 1277 | - | else | ||
| 1278 | 95 | 18,19 | error = git_reference__update_terminal( | |
| 1279 | - | repo, ref_name, id, who, git_buf_cstr(&reflog_msg)); | ||
| 1280 | - | |||
| 1281 | - | done: | ||
| 1282 | 126 | 20 | git_reference_free(ref_new); | |
| 1283 | 126 | 21 | git_buf_dispose(&reflog_msg); | |
| 1284 | 126 | 22 | git_commit_free(commit); | |
| 1285 | 126 | 23 | return error; | |
| 1286 | - | } | ||
| 1287 | - | |||
| 1288 | ![]() |
8 | 2 | int git_reference_has_log(git_repository *repo, const char *refname) |
| 1289 | - | { | ||
| 1290 | - | int error; | ||
| 1291 | - | git_refdb *refdb; | ||
| 1292 | - | |||
| 1293 | 8 | 2-4 | assert(repo && refname); | |
| 1294 | - | |||
| 1295 | 8 | 5,6 | if ((error = git_repository_refdb__weakptr(&refdb, repo)) < 0) | |
| 1296 | ##### | 7 | return error; | |
| 1297 | - | |||
| 1298 | 8 | 8 | return git_refdb_has_log(refdb, refname); | |
| 1299 | - | } | ||
| 1300 | - | |||
| 1301 | ![]() |
61 | 2 | int git_reference_ensure_log(git_repository *repo, const char *refname) |
| 1302 | - | { | ||
| 1303 | - | int error; | ||
| 1304 | - | git_refdb *refdb; | ||
| 1305 | - | |||
| 1306 | 61 | 2-4 | assert(repo && refname); | |
| 1307 | - | |||
| 1308 | 61 | 5,6 | if ((error = git_repository_refdb__weakptr(&refdb, repo)) < 0) | |
| 1309 | ##### | 7 | return error; | |
| 1310 | - | |||
| 1311 | 61 | 8 | return git_refdb_ensure_log(refdb, refname); | |
| 1312 | - | } | ||
| 1313 | - | |||
| 1314 | 731 | 2 | int git_reference__is_branch(const char *ref_name) | |
| 1315 | - | { | ||
| 1316 | 731 | 2 | return git__prefixcmp(ref_name, GIT_REFS_HEADS_DIR) == 0; | |
| 1317 | - | } | ||
| 1318 | - | |||
| 1319 | 394 | 2 | int git_reference_is_branch(const git_reference *ref) | |
| 1320 | - | { | ||
| 1321 | 394 | 2,3 | assert(ref); | |
| 1322 | 394 | 4 | return git_reference__is_branch(ref->name); | |
| 1323 | - | } | ||
| 1324 | - | |||
| 1325 | 82 | 2 | int git_reference__is_remote(const char *ref_name) | |
| 1326 | - | { | ||
| 1327 | 82 | 2 | return git__prefixcmp(ref_name, GIT_REFS_REMOTES_DIR) == 0; | |
| 1328 | - | } | ||
| 1329 | - | |||
| 1330 | 7 | 2 | int git_reference_is_remote(const git_reference *ref) | |
| 1331 | - | { | ||
| 1332 | 7 | 2,3 | assert(ref); | |
| 1333 | 7 | 4 | return git_reference__is_remote(ref->name); | |
| 1334 | - | } | ||
| 1335 | - | |||
| 1336 | 73 | 2 | int git_reference__is_tag(const char *ref_name) | |
| 1337 | - | { | ||
| 1338 | 73 | 2 | return git__prefixcmp(ref_name, GIT_REFS_TAGS_DIR) == 0; | |
| 1339 | - | } | ||
| 1340 | - | |||
| 1341 | 11 | 2 | int git_reference_is_tag(const git_reference *ref) | |
| 1342 | - | { | ||
| 1343 | 11 | 2,3 | assert(ref); | |
| 1344 | 11 | 4 | return git_reference__is_tag(ref->name); | |
| 1345 | - | } | ||
| 1346 | - | |||
| 1347 | 3 | 2 | int git_reference__is_note(const char *ref_name) | |
| 1348 | - | { | ||
| 1349 | 3 | 2 | return git__prefixcmp(ref_name, GIT_REFS_NOTES_DIR) == 0; | |
| 1350 | - | } | ||
| 1351 | - | |||
| 1352 | 3 | 2 | int git_reference_is_note(const git_reference *ref) | |
| 1353 | - | { | ||
| 1354 | 3 | 2,3 | assert(ref); | |
| 1355 | 3 | 4 | return git_reference__is_note(ref->name); | |
| 1356 | - | } | ||
| 1357 | - | |||
| 1358 | ##### | 2 | static int peel_error(int error, const git_reference *ref, const char* msg) | |
| 1359 | - | { | ||
| 1360 | ##### | 2,3 | git_error_set( | |
| 1361 | - | GIT_ERROR_INVALID, | ||
| 1362 | - | "the reference '%s' cannot be peeled - %s", git_reference_name(ref), msg); | ||
| 1363 | ##### | 4 | return error; | |
| 1364 | - | } | ||
| 1365 | - | |||
| 1366 | ![]() |
4105 | 2 | int git_reference_peel( |
| 1367 | - | git_object **peeled, | ||
| 1368 | - | const git_reference *ref, | ||
| 1369 | - | git_object_t target_type) | ||
| 1370 | - | { | ||
| 1371 | 4105 | 2 | const git_reference *resolved = NULL; | |
| 1372 | 4105 | 2 | git_reference *allocated = NULL; | |
| 1373 | 4105 | 2 | git_object *target = NULL; | |
| 1374 | - | int error; | ||
| 1375 | - | |||
| 1376 | 4105 | 2,3 | assert(ref); | |
| 1377 | - | |||
| 1378 | 4105 | 4 | if (ref->type == GIT_REFERENCE_DIRECT) { | |
| 1379 | 3969 | 5 | resolved = ref; | |
| 1380 | - | } else { | ||
| 1381 | 136 | 6,7 | if ((error = git_reference_resolve(&allocated, ref)) < 0) | |
| 1382 | ##### | 8 | return peel_error(error, ref, "Cannot resolve reference"); | |
| 1383 | - | |||
| 1384 | 136 | 9 | resolved = allocated; | |
| 1385 | - | } | ||
| 1386 | - | |||
| 1387 | - | /* | ||
| 1388 | - | * If we try to peel an object to a tag, we cannot use | ||
| 1389 | - | * the fully peeled object, as that will always resolve | ||
| 1390 | - | * to a commit. So we only want to use the peeled value | ||
| 1391 | - | * if it is not zero and the target is not a tag. | ||
| 1392 | - | */ | ||
| 1393 | 4105 | 10-12 | if (target_type != GIT_OBJECT_TAG && !git_oid_is_zero(&resolved->peel)) { | |
| 1394 | 2 | 13,14 | error = git_object_lookup(&target, | |
| 1395 | - | git_reference_owner(ref), &resolved->peel, GIT_OBJECT_ANY); | ||
| 1396 | - | } else { | ||
| 1397 | 4103 | 15,16 | error = git_object_lookup(&target, | |
| 1398 | - | git_reference_owner(ref), &resolved->target.oid, GIT_OBJECT_ANY); | ||
| 1399 | - | } | ||
| 1400 | - | |||
| 1401 | 4105 | 17 | if (error < 0) { | |
| 1402 | ##### | 18 | peel_error(error, ref, "Cannot retrieve reference target"); | |
| 1403 | ##### | 19 | goto cleanup; | |
| 1404 | - | } | ||
| 1405 | - | |||
| 1406 | 4105 | 20-22 | if (target_type == GIT_OBJECT_ANY && git_object_type(target) != GIT_OBJECT_TAG) | |
| 1407 | 56 | 23 | error = git_object_dup(peeled, target); | |
| 1408 | - | else | ||
| 1409 | 4049 | 24 | error = git_object_peel(peeled, target, target_type); | |
| 1410 | - | |||
| 1411 | - | cleanup: | ||
| 1412 | 4105 | 25 | git_object_free(target); | |
| 1413 | 4105 | 26 | git_reference_free(allocated); | |
| 1414 | - | |||
| 1415 | 4105 | 27 | return error; | |
| 1416 | - | } | ||
| 1417 | - | |||
| 1418 | 18387 | 2 | int git_reference__is_valid_name(const char *refname, unsigned int flags) | |
| 1419 | - | { | ||
| 1420 | 18387 | 2,3 | if (git_reference__normalize_name(NULL, refname, flags) < 0) { | |
| 1421 | 1521 | 4 | git_error_clear(); | |
| 1422 | 1521 | 5 | return false; | |
| 1423 | - | } | ||
| 1424 | - | |||
| 1425 | 16866 | 6 | return true; | |
| 1426 | - | } | ||
| 1427 | - | |||
| 1428 | 14532 | 2 | int git_reference_is_valid_name(const char *refname) | |
| 1429 | - | { | ||
| 1430 | 14532 | 2 | return git_reference__is_valid_name(refname, GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL); | |
| 1431 | - | } | ||
| 1432 | - | |||
| 1433 | 270 | 2 | const char *git_reference__shorthand(const char *name) | |
| 1434 | - | { | ||
| 1435 | 270 | 2,3 | if (!git__prefixcmp(name, GIT_REFS_HEADS_DIR)) | |
| 1436 | 241 | 4 | return name + strlen(GIT_REFS_HEADS_DIR); | |
| 1437 | 29 | 5,6 | else if (!git__prefixcmp(name, GIT_REFS_TAGS_DIR)) | |
| 1438 | 7 | 7 | return name + strlen(GIT_REFS_TAGS_DIR); | |
| 1439 | 22 | 8,9 | else if (!git__prefixcmp(name, GIT_REFS_REMOTES_DIR)) | |
| 1440 | 21 | 10 | return name + strlen(GIT_REFS_REMOTES_DIR); | |
| 1441 | 1 | 11,12 | else if (!git__prefixcmp(name, GIT_REFS_DIR)) | |
| 1442 | 1 | 13 | return name + strlen(GIT_REFS_DIR); | |
| 1443 | - | |||
| 1444 | - | /* No shorthands are avaiable, so just return the name */ | ||
| 1445 | ##### | 14 | return name; | |
| 1446 | - | } | ||
| 1447 | - | |||
| 1448 | 26 | 2 | const char *git_reference_shorthand(const git_reference *ref) | |
| 1449 | - | { | ||
| 1450 | 26 | 2 | return git_reference__shorthand(ref->name); | |
| 1451 | - | } | ||
| 1452 | - | |||
| 1453 | ![]() |
18 | 2 | int git_reference__is_unborn_head(bool *unborn, const git_reference *ref, git_repository *repo) |
| 1454 | - | { | ||
| 1455 | - | int error; | ||
| 1456 | - | git_reference *tmp_ref; | ||
| 1457 | 18 | 2-5 | assert(unborn && ref && repo); | |
| 1458 | - | |||
| 1459 | 18 | 6 | if (ref->type == GIT_REFERENCE_DIRECT) { | |
| 1460 | 4 | 7 | *unborn = 0; | |
| 1461 | 4 | 7 | return 0; | |
| 1462 | - | } | ||
| 1463 | - | |||
| 1464 | 14 | 8 | error = git_reference_lookup_resolved(&tmp_ref, repo, ref->name, -1); | |
| 1465 | 14 | 9 | git_reference_free(tmp_ref); | |
| 1466 | - | |||
| 1467 | 14 | 10,11 | if (error != 0 && error != GIT_ENOTFOUND) | |
| 1468 | ##### | 12 | return error; | |
| 1469 | 14 | 13,14 | else if (error == GIT_ENOTFOUND && git__strcmp(ref->name, GIT_HEAD_FILE) == 0) | |
| 1470 | 2 | 15 | *unborn = true; | |
| 1471 | - | else | ||
| 1472 | 12 | 16 | *unborn = false; | |
| 1473 | - | |||
| 1474 | 14 | 17 | return 0; | |
| 1475 | - | } |