object: add repository argument to create_object
[git] / tag.c
1 #include "cache.h"
2 #include "tag.h"
3 #include "commit.h"
4 #include "tree.h"
5 #include "blob.h"
6 #include "gpg-interface.h"
7
8 const char *tag_type = "tag";
9
10 static int run_gpg_verify(const char *buf, unsigned long size, unsigned flags)
11 {
12         struct signature_check sigc;
13         size_t payload_size;
14         int ret;
15
16         memset(&sigc, 0, sizeof(sigc));
17
18         payload_size = parse_signature(buf, size);
19
20         if (size == payload_size) {
21                 if (flags & GPG_VERIFY_VERBOSE)
22                         write_in_full(1, buf, payload_size);
23                 return error("no signature found");
24         }
25
26         ret = check_signature(buf, payload_size, buf + payload_size,
27                                 size - payload_size, &sigc);
28
29         if (!(flags & GPG_VERIFY_OMIT_STATUS))
30                 print_signature_buffer(&sigc, flags);
31
32         signature_check_clear(&sigc);
33         return ret;
34 }
35
36 int gpg_verify_tag(const struct object_id *oid, const char *name_to_report,
37                 unsigned flags)
38 {
39         enum object_type type;
40         char *buf;
41         unsigned long size;
42         int ret;
43
44         type = oid_object_info(the_repository, oid, NULL);
45         if (type != OBJ_TAG)
46                 return error("%s: cannot verify a non-tag object of type %s.",
47                                 name_to_report ?
48                                 name_to_report :
49                                 find_unique_abbrev(oid, DEFAULT_ABBREV),
50                                 type_name(type));
51
52         buf = read_object_file(oid, &type, &size);
53         if (!buf)
54                 return error("%s: unable to read file.",
55                                 name_to_report ?
56                                 name_to_report :
57                                 find_unique_abbrev(oid, DEFAULT_ABBREV));
58
59         ret = run_gpg_verify(buf, size, flags);
60
61         free(buf);
62         return ret;
63 }
64
65 struct object *deref_tag(struct object *o, const char *warn, int warnlen)
66 {
67         while (o && o->type == OBJ_TAG)
68                 if (((struct tag *)o)->tagged)
69                         o = parse_object(&((struct tag *)o)->tagged->oid);
70                 else
71                         o = NULL;
72         if (!o && warn) {
73                 if (!warnlen)
74                         warnlen = strlen(warn);
75                 error("missing object referenced by '%.*s'", warnlen, warn);
76         }
77         return o;
78 }
79
80 struct object *deref_tag_noverify(struct object *o)
81 {
82         while (o && o->type == OBJ_TAG) {
83                 o = parse_object(&o->oid);
84                 if (o && o->type == OBJ_TAG && ((struct tag *)o)->tagged)
85                         o = ((struct tag *)o)->tagged;
86                 else
87                         o = NULL;
88         }
89         return o;
90 }
91
92 struct tag *lookup_tag(const struct object_id *oid)
93 {
94         struct object *obj = lookup_object(oid->hash);
95         if (!obj)
96                 return create_object(the_repository, oid->hash,
97                                      alloc_tag_node());
98         return object_as_type(obj, OBJ_TAG, 0);
99 }
100
101 static timestamp_t parse_tag_date(const char *buf, const char *tail)
102 {
103         const char *dateptr;
104
105         while (buf < tail && *buf++ != '>')
106                 /* nada */;
107         if (buf >= tail)
108                 return 0;
109         dateptr = buf;
110         while (buf < tail && *buf++ != '\n')
111                 /* nada */;
112         if (buf >= tail)
113                 return 0;
114         /* dateptr < buf && buf[-1] == '\n', so parsing will stop at buf-1 */
115         return parse_timestamp(dateptr, NULL, 10);
116 }
117
118 int parse_tag_buffer(struct tag *item, const void *data, unsigned long size)
119 {
120         struct object_id oid;
121         char type[20];
122         const char *bufptr = data;
123         const char *tail = bufptr + size;
124         const char *nl;
125
126         if (item->object.parsed)
127                 return 0;
128         item->object.parsed = 1;
129
130         if (size < GIT_SHA1_HEXSZ + 24)
131                 return -1;
132         if (memcmp("object ", bufptr, 7) || parse_oid_hex(bufptr + 7, &oid, &bufptr) || *bufptr++ != '\n')
133                 return -1;
134
135         if (!starts_with(bufptr, "type "))
136                 return -1;
137         bufptr += 5;
138         nl = memchr(bufptr, '\n', tail - bufptr);
139         if (!nl || sizeof(type) <= (nl - bufptr))
140                 return -1;
141         memcpy(type, bufptr, nl - bufptr);
142         type[nl - bufptr] = '\0';
143         bufptr = nl + 1;
144
145         if (!strcmp(type, blob_type)) {
146                 item->tagged = (struct object *)lookup_blob(&oid);
147         } else if (!strcmp(type, tree_type)) {
148                 item->tagged = (struct object *)lookup_tree(&oid);
149         } else if (!strcmp(type, commit_type)) {
150                 item->tagged = (struct object *)lookup_commit(&oid);
151         } else if (!strcmp(type, tag_type)) {
152                 item->tagged = (struct object *)lookup_tag(&oid);
153         } else {
154                 error("Unknown type %s", type);
155                 item->tagged = NULL;
156         }
157
158         if (bufptr + 4 < tail && starts_with(bufptr, "tag "))
159                 ;               /* good */
160         else
161                 return -1;
162         bufptr += 4;
163         nl = memchr(bufptr, '\n', tail - bufptr);
164         if (!nl)
165                 return -1;
166         item->tag = xmemdupz(bufptr, nl - bufptr);
167         bufptr = nl + 1;
168
169         if (bufptr + 7 < tail && starts_with(bufptr, "tagger "))
170                 item->date = parse_tag_date(bufptr, tail);
171         else
172                 item->date = 0;
173
174         return 0;
175 }
176
177 int parse_tag(struct tag *item)
178 {
179         enum object_type type;
180         void *data;
181         unsigned long size;
182         int ret;
183
184         if (item->object.parsed)
185                 return 0;
186         data = read_object_file(&item->object.oid, &type, &size);
187         if (!data)
188                 return error("Could not read %s",
189                              oid_to_hex(&item->object.oid));
190         if (type != OBJ_TAG) {
191                 free(data);
192                 return error("Object %s not a tag",
193                              oid_to_hex(&item->object.oid));
194         }
195         ret = parse_tag_buffer(item, data, size);
196         free(data);
197         return ret;
198 }