Git fork
at reftables-rust 245 lines 6.0 kB view raw
1#define USE_THE_REPOSITORY_VARIABLE 2#define DISABLE_SIGN_COMPARE_WARNINGS 3 4#include "git-compat-util.h" 5#include "environment.h" 6#include "tag.h" 7#include "object-name.h" 8#include "odb.h" 9#include "commit.h" 10#include "tree.h" 11#include "blob.h" 12#include "alloc.h" 13#include "gpg-interface.h" 14#include "hex.h" 15#include "packfile.h" 16 17const char *tag_type = "tag"; 18 19static int run_gpg_verify(const char *buf, unsigned long size, unsigned flags) 20{ 21 struct signature_check sigc; 22 struct strbuf payload = STRBUF_INIT; 23 struct strbuf signature = STRBUF_INIT; 24 int ret; 25 26 memset(&sigc, 0, sizeof(sigc)); 27 28 if (!parse_signature(buf, size, &payload, &signature)) { 29 if (flags & GPG_VERIFY_VERBOSE) 30 write_in_full(1, buf, size); 31 return error("no signature found"); 32 } 33 34 sigc.payload_type = SIGNATURE_PAYLOAD_TAG; 35 sigc.payload = strbuf_detach(&payload, &sigc.payload_len); 36 ret = check_signature(&sigc, signature.buf, signature.len); 37 38 if (!(flags & GPG_VERIFY_OMIT_STATUS)) 39 print_signature_buffer(&sigc, flags); 40 41 signature_check_clear(&sigc); 42 strbuf_release(&payload); 43 strbuf_release(&signature); 44 return ret; 45} 46 47int gpg_verify_tag(const struct object_id *oid, const char *name_to_report, 48 unsigned flags) 49{ 50 enum object_type type; 51 char *buf; 52 unsigned long size; 53 int ret; 54 55 type = odb_read_object_info(the_repository->objects, oid, NULL); 56 if (type != OBJ_TAG) 57 return error("%s: cannot verify a non-tag object of type %s.", 58 name_to_report ? 59 name_to_report : 60 repo_find_unique_abbrev(the_repository, oid, DEFAULT_ABBREV), 61 type_name(type)); 62 63 buf = odb_read_object(the_repository->objects, oid, &type, &size); 64 if (!buf) 65 return error("%s: unable to read file.", 66 name_to_report ? 67 name_to_report : 68 repo_find_unique_abbrev(the_repository, oid, DEFAULT_ABBREV)); 69 70 ret = run_gpg_verify(buf, size, flags); 71 72 free(buf); 73 return ret; 74} 75 76struct object *deref_tag(struct repository *r, struct object *o, const char *warn, int warnlen) 77{ 78 struct object_id *last_oid = NULL; 79 while (o && o->type == OBJ_TAG) 80 if (((struct tag *)o)->tagged) { 81 last_oid = &((struct tag *)o)->tagged->oid; 82 o = parse_object(r, last_oid); 83 } else { 84 last_oid = NULL; 85 o = NULL; 86 } 87 if (!o && warn) { 88 if (last_oid && is_promisor_object(r, last_oid)) 89 return NULL; 90 if (!warnlen) 91 warnlen = strlen(warn); 92 error("missing object referenced by '%.*s'", warnlen, warn); 93 } 94 return o; 95} 96 97struct object *deref_tag_noverify(struct repository *r, struct object *o) 98{ 99 while (o && o->type == OBJ_TAG) { 100 o = parse_object(r, &o->oid); 101 if (o && o->type == OBJ_TAG && ((struct tag *)o)->tagged) 102 o = ((struct tag *)o)->tagged; 103 else 104 o = NULL; 105 } 106 return o; 107} 108 109struct tag *lookup_tag(struct repository *r, const struct object_id *oid) 110{ 111 struct object *obj = lookup_object(r, oid); 112 if (!obj) 113 return create_object(r, oid, alloc_tag_node(r)); 114 return object_as_type(obj, OBJ_TAG, 0); 115} 116 117static timestamp_t parse_tag_date(const char *buf, const char *tail) 118{ 119 const char *dateptr; 120 121 while (buf < tail && *buf++ != '>') 122 /* nada */; 123 if (buf >= tail) 124 return 0; 125 dateptr = buf; 126 while (buf < tail && *buf++ != '\n') 127 /* nada */; 128 if (buf >= tail) 129 return 0; 130 /* dateptr < buf && buf[-1] == '\n', so parsing will stop at buf-1 */ 131 return parse_timestamp(dateptr, NULL, 10); 132} 133 134void release_tag_memory(struct tag *t) 135{ 136 free(t->tag); 137 t->tagged = NULL; 138 t->object.parsed = 0; 139 t->date = 0; 140} 141 142int parse_tag_buffer(struct repository *r, struct tag *item, const void *data, unsigned long size) 143{ 144 struct object_id oid; 145 char type[20]; 146 const char *bufptr = data; 147 const char *tail = bufptr + size; 148 const char *nl; 149 150 if (item->object.parsed) 151 return 0; 152 153 if (item->tag) { 154 /* 155 * Presumably left over from a previous failed parse; 156 * clear it out in preparation for re-parsing (we'll probably 157 * hit the same error, which lets us tell our current caller 158 * about the problem). 159 */ 160 FREE_AND_NULL(item->tag); 161 } 162 163 if (size < the_hash_algo->hexsz + 24) 164 return -1; 165 if (memcmp("object ", bufptr, 7) || parse_oid_hex(bufptr + 7, &oid, &bufptr) || *bufptr++ != '\n') 166 return -1; 167 168 if (!starts_with(bufptr, "type ")) 169 return -1; 170 bufptr += 5; 171 nl = memchr(bufptr, '\n', tail - bufptr); 172 if (!nl || sizeof(type) <= (nl - bufptr)) 173 return -1; 174 memcpy(type, bufptr, nl - bufptr); 175 type[nl - bufptr] = '\0'; 176 bufptr = nl + 1; 177 178 if (!strcmp(type, blob_type)) { 179 item->tagged = (struct object *)lookup_blob(r, &oid); 180 } else if (!strcmp(type, tree_type)) { 181 item->tagged = (struct object *)lookup_tree(r, &oid); 182 } else if (!strcmp(type, commit_type)) { 183 item->tagged = (struct object *)lookup_commit(r, &oid); 184 } else if (!strcmp(type, tag_type)) { 185 item->tagged = (struct object *)lookup_tag(r, &oid); 186 } else { 187 return error("unknown tag type '%s' in %s", 188 type, oid_to_hex(&item->object.oid)); 189 } 190 191 if (!item->tagged) 192 return error("bad tag pointer to %s in %s", 193 oid_to_hex(&oid), 194 oid_to_hex(&item->object.oid)); 195 196 if (bufptr + 4 < tail && starts_with(bufptr, "tag ")) 197 ; /* good */ 198 else 199 return -1; 200 bufptr += 4; 201 nl = memchr(bufptr, '\n', tail - bufptr); 202 if (!nl) 203 return -1; 204 item->tag = xmemdupz(bufptr, nl - bufptr); 205 bufptr = nl + 1; 206 207 if (bufptr + 7 < tail && starts_with(bufptr, "tagger ")) 208 item->date = parse_tag_date(bufptr, tail); 209 else 210 item->date = 0; 211 212 item->object.parsed = 1; 213 return 0; 214} 215 216int parse_tag(struct tag *item) 217{ 218 enum object_type type; 219 void *data; 220 unsigned long size; 221 int ret; 222 223 if (item->object.parsed) 224 return 0; 225 data = odb_read_object(the_repository->objects, &item->object.oid, 226 &type, &size); 227 if (!data) 228 return error("Could not read %s", 229 oid_to_hex(&item->object.oid)); 230 if (type != OBJ_TAG) { 231 free(data); 232 return error("Object %s not a tag", 233 oid_to_hex(&item->object.oid)); 234 } 235 ret = parse_tag_buffer(the_repository, item, data, size); 236 free(data); 237 return ret; 238} 239 240struct object_id *get_tagged_oid(struct tag *tag) 241{ 242 if (!tag->tagged) 243 die("bad tag"); 244 return &tag->tagged->oid; 245}