int ref_transaction_update(struct ref_transaction *transaction, const char *refname, const unsigned char *new_sha1, const unsigned char *old_sha1, unsigned int flags, const char *msg, struct strbuf *err) { assert(err); if ((new_sha1 && !is_null_sha1(new_sha1)) ? check_refname_format(refname, REFNAME_ALLOW_ONELEVEL) : !refname_is_safe(refname)) { strbuf_addf(err, "refusing to update ref with bad name '%s'", refname); return -1; } flags |= (new_sha1 ? REF_HAVE_NEW : 0) | (old_sha1 ? REF_HAVE_OLD : 0); ref_transaction_add_update(transaction, refname, flags, new_sha1, old_sha1, msg); return 0; }
/* * Move the iterator to the next record in the snapshot, without * respect for whether the record is actually required by the current * iteration. Adjust the fields in `iter` and return `ITER_OK` or * `ITER_DONE`. This function does not free the iterator in the case * of `ITER_DONE`. */ static int next_record(struct packed_ref_iterator *iter) { const char *p = iter->pos, *eol; strbuf_reset(&iter->refname_buf); if (iter->pos == iter->eof) return ITER_DONE; iter->base.flags = REF_ISPACKED; if (iter->eof - p < GIT_SHA1_HEXSZ + 2 || parse_oid_hex(p, &iter->oid, &p) || !isspace(*p++)) die_invalid_line(iter->snapshot->refs->path, iter->pos, iter->eof - iter->pos); eol = memchr(p, '\n', iter->eof - p); if (!eol) die_unterminated_line(iter->snapshot->refs->path, iter->pos, iter->eof - iter->pos); strbuf_add(&iter->refname_buf, p, eol - p); iter->base.refname = iter->refname_buf.buf; if (check_refname_format(iter->base.refname, REFNAME_ALLOW_ONELEVEL)) { if (!refname_is_safe(iter->base.refname)) die("packed refname is dangerous: %s", iter->base.refname); oidclr(&iter->oid); iter->base.flags |= REF_BAD_NAME | REF_ISBROKEN; } if (iter->snapshot->peeled == PEELED_FULLY || (iter->snapshot->peeled == PEELED_TAGS && starts_with(iter->base.refname, "refs/tags/"))) iter->base.flags |= REF_KNOWS_PEELED; iter->pos = eol + 1; if (iter->pos < iter->eof && *iter->pos == '^') { p = iter->pos + 1; if (iter->eof - p < GIT_SHA1_HEXSZ + 1 || parse_oid_hex(p, &iter->peeled, &p) || *p++ != '\n') die_invalid_line(iter->snapshot->refs->path, iter->pos, iter->eof - iter->pos); iter->pos = p; /* * Regardless of what the file header said, we * definitely know the value of *this* reference. But * we suppress it if the reference is broken: */ if ((iter->base.flags & REF_ISBROKEN)) { oidclr(&iter->peeled); iter->base.flags &= ~REF_KNOWS_PEELED; } else { iter->base.flags |= REF_KNOWS_PEELED; } } else { oidclr(&iter->peeled); } return ITER_OK; }
/* This function needs to return a meaningful errno on failure */ static const char *resolve_ref_recursively(struct ref_store *refs, const char *refname, int resolve_flags, unsigned char *sha1, int *flags) { static struct strbuf sb_refname = STRBUF_INIT; int unused_flags; int symref_count; if (!flags) flags = &unused_flags; *flags = 0; if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL)) { if (!(resolve_flags & RESOLVE_REF_ALLOW_BAD_NAME) || !refname_is_safe(refname)) { errno = EINVAL; return NULL; } /* * dwim_ref() uses REF_ISBROKEN to distinguish between * missing refs and refs that were present but invalid, * to complain about the latter to stderr. * * We don't know whether the ref exists, so don't set * REF_ISBROKEN yet. */ *flags |= REF_BAD_NAME; } for (symref_count = 0; symref_count < SYMREF_MAXDEPTH; symref_count++) { unsigned int read_flags = 0; if (refs->be->read_raw_ref(refs, refname, sha1, &sb_refname, &read_flags)) { *flags |= read_flags; if (errno != ENOENT || (resolve_flags & RESOLVE_REF_READING)) return NULL; hashclr(sha1); if (*flags & REF_BAD_NAME) *flags |= REF_ISBROKEN; return refname; } *flags |= read_flags; if (!(read_flags & REF_ISSYMREF)) { if (*flags & REF_BAD_NAME) { hashclr(sha1); *flags |= REF_ISBROKEN; } return refname; } refname = sb_refname.buf; if (resolve_flags & RESOLVE_REF_NO_RECURSE) { hashclr(sha1); return refname; } if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL)) { if (!(resolve_flags & RESOLVE_REF_ALLOW_BAD_NAME) || !refname_is_safe(refname)) { errno = EINVAL; return NULL; } *flags |= REF_ISBROKEN | REF_BAD_NAME; } } errno = ELOOP; return NULL; }