blob: 1db663d71623a493286c90b13532c7d1cf73f517 [file] [log] [blame]
Daniel Barkalow2636f612005-04-28 07:46:33 -07001#include "cache.h"
Junio C Hamano8f1d2e62006-01-07 01:33:54 -08002#include "tag.h"
Stefan Bellercbd53a22018-05-15 16:42:15 -07003#include "object-store.h"
Nicolas Pitre0ab17952007-02-26 14:56:00 -05004#include "commit.h"
5#include "tree.h"
6#include "blob.h"
Stefan Beller14ba97f2018-05-15 14:48:42 -07007#include "alloc.h"
Lukas Puehringer94240b92017-01-17 18:37:18 -05008#include "gpg-interface.h"
Jonathan Tan8c4cc322018-07-12 17:03:07 -07009#include "packfile.h"
Daniel Barkalow2636f612005-04-28 07:46:33 -070010
11const char *tag_type = "tag";
12
Santiago Torres45a227e2016-04-22 10:52:04 -040013static int run_gpg_verify(const char *buf, unsigned long size, unsigned flags)
14{
15 struct signature_check sigc;
16 size_t payload_size;
17 int ret;
18
19 memset(&sigc, 0, sizeof(sigc));
20
21 payload_size = parse_signature(buf, size);
22
23 if (size == payload_size) {
24 if (flags & GPG_VERIFY_VERBOSE)
25 write_in_full(1, buf, payload_size);
26 return error("no signature found");
27 }
28
29 ret = check_signature(buf, payload_size, buf + payload_size,
30 size - payload_size, &sigc);
Lukas Puehringer94240b92017-01-17 18:37:18 -050031
32 if (!(flags & GPG_VERIFY_OMIT_STATUS))
33 print_signature_buffer(&sigc, flags);
Santiago Torres45a227e2016-04-22 10:52:04 -040034
35 signature_check_clear(&sigc);
36 return ret;
37}
38
Stefan Beller84571762017-07-12 17:44:15 -070039int gpg_verify_tag(const struct object_id *oid, const char *name_to_report,
Santiago Torres45a227e2016-04-22 10:52:04 -040040 unsigned flags)
41{
42 enum object_type type;
43 char *buf;
44 unsigned long size;
45 int ret;
46
Stefan Beller0df8e962018-04-25 11:20:59 -070047 type = oid_object_info(the_repository, oid, NULL);
Santiago Torres45a227e2016-04-22 10:52:04 -040048 if (type != OBJ_TAG)
49 return error("%s: cannot verify a non-tag object of type %s.",
50 name_to_report ?
51 name_to_report :
brian m. carlsonaab95832018-03-12 02:27:30 +000052 find_unique_abbrev(oid, DEFAULT_ABBREV),
Brandon Williamsdebca9d2018-02-14 10:59:24 -080053 type_name(type));
Santiago Torres45a227e2016-04-22 10:52:04 -040054
brian m. carlsonb4f5aca2018-03-12 02:27:53 +000055 buf = read_object_file(oid, &type, &size);
Santiago Torres45a227e2016-04-22 10:52:04 -040056 if (!buf)
57 return error("%s: unable to read file.",
58 name_to_report ?
59 name_to_report :
brian m. carlsonaab95832018-03-12 02:27:30 +000060 find_unique_abbrev(oid, DEFAULT_ABBREV));
Santiago Torres45a227e2016-04-22 10:52:04 -040061
62 ret = run_gpg_verify(buf, size, flags);
63
64 free(buf);
65 return ret;
66}
67
Stefan Beller286d2582018-06-28 18:22:20 -070068struct object *deref_tag(struct repository *r, struct object *o, const char *warn, int warnlen)
Junio C Hamano37fde872005-08-05 00:47:56 -070069{
Jonathan Tan8c4cc322018-07-12 17:03:07 -070070 struct object_id *last_oid = NULL;
Linus Torvalds19746322006-07-11 20:45:31 -070071 while (o && o->type == OBJ_TAG)
Jonathan Tan8c4cc322018-07-12 17:03:07 -070072 if (((struct tag *)o)->tagged) {
73 last_oid = &((struct tag *)o)->tagged->oid;
Junio C Hamano09ca6132018-08-02 15:30:46 -070074 o = parse_object(r, last_oid);
Jonathan Tan8c4cc322018-07-12 17:03:07 -070075 } else {
76 last_oid = NULL;
Martin Koegler24e8a3c2008-02-18 08:31:55 +010077 o = NULL;
Jonathan Tan8c4cc322018-07-12 17:03:07 -070078 }
Junio C Hamano9534f402005-11-02 15:19:13 -080079 if (!o && warn) {
Jonathan Tan8c4cc322018-07-12 17:03:07 -070080 if (last_oid && is_promisor_object(last_oid))
81 return NULL;
Junio C Hamano9534f402005-11-02 15:19:13 -080082 if (!warnlen)
83 warnlen = strlen(warn);
84 error("missing object referenced by '%.*s'", warnlen, warn);
85 }
Junio C Hamano37fde872005-08-05 00:47:56 -070086 return o;
87}
88
Jeff King90108a22012-01-06 14:18:01 -050089struct object *deref_tag_noverify(struct object *o)
90{
91 while (o && o->type == OBJ_TAG) {
Stefan Beller109cd762018-06-28 18:21:51 -070092 o = parse_object(the_repository, &o->oid);
Jeff King90108a22012-01-06 14:18:01 -050093 if (o && o->type == OBJ_TAG && ((struct tag *)o)->tagged)
94 o = ((struct tag *)o)->tagged;
95 else
96 o = NULL;
97 }
98 return o;
99}
100
Stefan Beller8bde69b2018-06-28 18:22:11 -0700101struct tag *lookup_tag(struct repository *r, const struct object_id *oid)
Daniel Barkalow2636f612005-04-28 07:46:33 -0700102{
Stefan Beller8bde69b2018-06-28 18:22:11 -0700103 struct object *obj = lookup_object(r, oid->hash);
Linus Torvalds100c5f32007-04-16 22:11:43 -0700104 if (!obj)
Stefan Beller8bde69b2018-06-28 18:22:11 -0700105 return create_object(r, oid->hash,
106 alloc_tag_node(r));
107 return object_as_type(r, obj, OBJ_TAG, 0);
Daniel Barkalow2636f612005-04-28 07:46:33 -0700108}
109
Johannes Schindelindddbad72017-04-26 21:29:31 +0200110static timestamp_t parse_tag_date(const char *buf, const char *tail)
Shawn O. Pearcee451d062010-04-12 16:25:28 -0700111{
112 const char *dateptr;
113
114 while (buf < tail && *buf++ != '>')
115 /* nada */;
116 if (buf >= tail)
117 return 0;
118 dateptr = buf;
119 while (buf < tail && *buf++ != '\n')
120 /* nada */;
121 if (buf >= tail)
122 return 0;
Johannes Schindelin1aeb7e72017-04-21 12:45:44 +0200123 /* dateptr < buf && buf[-1] == '\n', so parsing will stop at buf-1 */
124 return parse_timestamp(dateptr, NULL, 10);
Shawn O. Pearcee451d062010-04-12 16:25:28 -0700125}
126
Stefan Beller14ba97f2018-05-15 14:48:42 -0700127void release_tag_memory(struct tag *t)
128{
129 free(t->tag);
130 t->tagged = NULL;
131 t->object.parsed = 0;
132 t->date = 0;
133}
134
Stefan Beller84f80cd2018-06-28 18:22:12 -0700135int parse_tag_buffer(struct repository *r, struct tag *item, const void *data, unsigned long size)
Daniel Barkalow2636f612005-04-28 07:46:33 -0700136{
brian m. carlson1e4085a2017-05-06 22:10:02 +0000137 struct object_id oid;
Daniel Barkalow89e42022005-06-21 20:35:10 -0400138 char type[20];
Shawn O. Pearce28de5b62010-04-12 16:25:27 -0700139 const char *bufptr = data;
140 const char *tail = bufptr + size;
141 const char *nl;
Edgar Toernigae200ee2005-04-30 09:51:03 -0700142
Shawn O. Pearce2e0052a2010-04-12 16:25:25 -0700143 if (item->object.parsed)
144 return 0;
145 item->object.parsed = 1;
Daniel Barkalow2636f612005-04-28 07:46:33 -0700146
brian m. carlson1e4085a2017-05-06 22:10:02 +0000147 if (size < GIT_SHA1_HEXSZ + 24)
Nicolas Pitrebd2c39f2005-05-06 13:48:34 -0400148 return -1;
brian m. carlson1e4085a2017-05-06 22:10:02 +0000149 if (memcmp("object ", bufptr, 7) || parse_oid_hex(bufptr + 7, &oid, &bufptr) || *bufptr++ != '\n')
Nicolas Pitrebd2c39f2005-05-06 13:48:34 -0400150 return -1;
Daniel Barkalow2636f612005-04-28 07:46:33 -0700151
Christian Couder59556542013-11-30 21:55:40 +0100152 if (!starts_with(bufptr, "type "))
Nicolas Pitrebd2c39f2005-05-06 13:48:34 -0400153 return -1;
Shawn O. Pearce28de5b62010-04-12 16:25:27 -0700154 bufptr += 5;
155 nl = memchr(bufptr, '\n', tail - bufptr);
156 if (!nl || sizeof(type) <= (nl - bufptr))
Nicolas Pitrebd2c39f2005-05-06 13:48:34 -0400157 return -1;
Jeff Kingeddda372015-09-24 17:08:26 -0400158 memcpy(type, bufptr, nl - bufptr);
Shawn O. Pearce28de5b62010-04-12 16:25:27 -0700159 type[nl - bufptr] = '\0';
160 bufptr = nl + 1;
Daniel Barkalow2636f612005-04-28 07:46:33 -0700161
Nicolas Pitre0ab17952007-02-26 14:56:00 -0500162 if (!strcmp(type, blob_type)) {
Stefan Beller84f80cd2018-06-28 18:22:12 -0700163 item->tagged = (struct object *)lookup_blob(r, &oid);
Nicolas Pitre0ab17952007-02-26 14:56:00 -0500164 } else if (!strcmp(type, tree_type)) {
Stefan Beller84f80cd2018-06-28 18:22:12 -0700165 item->tagged = (struct object *)lookup_tree(r, &oid);
Nicolas Pitre0ab17952007-02-26 14:56:00 -0500166 } else if (!strcmp(type, commit_type)) {
Stefan Beller84f80cd2018-06-28 18:22:12 -0700167 item->tagged = (struct object *)lookup_commit(r, &oid);
Nicolas Pitre0ab17952007-02-26 14:56:00 -0500168 } else if (!strcmp(type, tag_type)) {
Stefan Beller84f80cd2018-06-28 18:22:12 -0700169 item->tagged = (struct object *)lookup_tag(r, &oid);
Nicolas Pitre0ab17952007-02-26 14:56:00 -0500170 } else {
171 error("Unknown type %s", type);
172 item->tagged = NULL;
173 }
174
Christian Couder59556542013-11-30 21:55:40 +0100175 if (bufptr + 4 < tail && starts_with(bufptr, "tag "))
Nguyễn Thái Ngọc Duy85594252011-02-14 20:02:51 +0700176 ; /* good */
177 else
Shawn O. Pearce28de5b62010-04-12 16:25:27 -0700178 return -1;
179 bufptr += 4;
180 nl = memchr(bufptr, '\n', tail - bufptr);
181 if (!nl)
182 return -1;
183 item->tag = xmemdupz(bufptr, nl - bufptr);
184 bufptr = nl + 1;
185
Christian Couder59556542013-11-30 21:55:40 +0100186 if (bufptr + 7 < tail && starts_with(bufptr, "tagger "))
Shawn O. Pearcee451d062010-04-12 16:25:28 -0700187 item->date = parse_tag_date(bufptr, tail);
188 else
189 item->date = 0;
190
Daniel Barkalow2636f612005-04-28 07:46:33 -0700191 return 0;
Nicolas Pitrebd2c39f2005-05-06 13:48:34 -0400192}
Sergey Vlasov13019d42005-05-04 21:44:15 +0400193
Nicolas Pitrebd2c39f2005-05-06 13:48:34 -0400194int parse_tag(struct tag *item)
195{
Nicolas Pitre21666f12007-02-26 14:55:59 -0500196 enum object_type type;
Nicolas Pitrebd2c39f2005-05-06 13:48:34 -0400197 void *data;
198 unsigned long size;
199 int ret;
200
201 if (item->object.parsed)
202 return 0;
brian m. carlsonb4f5aca2018-03-12 02:27:53 +0000203 data = read_object_file(&item->object.oid, &type, &size);
Nicolas Pitrebd2c39f2005-05-06 13:48:34 -0400204 if (!data)
205 return error("Could not read %s",
brian m. carlsonf2fd0762015-11-10 02:22:28 +0000206 oid_to_hex(&item->object.oid));
Nicolas Pitre21666f12007-02-26 14:55:59 -0500207 if (type != OBJ_TAG) {
Nicolas Pitrebd2c39f2005-05-06 13:48:34 -0400208 free(data);
209 return error("Object %s not a tag",
brian m. carlsonf2fd0762015-11-10 02:22:28 +0000210 oid_to_hex(&item->object.oid));
Nicolas Pitrebd2c39f2005-05-06 13:48:34 -0400211 }
Stefan Beller0e740fe2018-06-28 18:22:04 -0700212 ret = parse_tag_buffer(the_repository, item, data, size);
Sergey Vlasov13019d42005-05-04 21:44:15 +0400213 free(data);
Nicolas Pitrebd2c39f2005-05-06 13:48:34 -0400214 return ret;
Daniel Barkalow2636f612005-04-28 07:46:33 -0700215}