worktree: move subcommand
[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 unsigned char *sha1, 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 = sha1_object_info(sha1, 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(sha1, DEFAULT_ABBREV),
50                                 typename(type));
51
52         buf = read_sha1_file(sha1, &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(sha1, 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.hash);
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.hash);
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 unsigned char *sha1)
93 {
94         struct object *obj = lookup_object(sha1);
95         if (!obj)
96                 return create_object(sha1, alloc_tag_node());
97         return object_as_type(obj, OBJ_TAG, 0);
98 }
99
100 static unsigned long parse_tag_date(const char *buf, const char *tail)
101 {
102         const char *dateptr;
103
104         while (buf < tail && *buf++ != '>')
105                 /* nada */;
106         if (buf >= tail)
107                 return 0;
108         dateptr = buf;
109         while (buf < tail && *buf++ != '\n')
110                 /* nada */;
111         if (buf >= tail)
112                 return 0;
113         /* dateptr < buf && buf[-1] == '\n', so strtoul will stop at buf-1 */
114         return strtoul(dateptr, NULL, 10);
115 }
116
117 int parse_tag_buffer(struct tag *item, const void *data, unsigned long size)
118 {
119         unsigned char sha1[20];
120         char type[20];
121         const char *bufptr = data;
122         const char *tail = bufptr + size;
123         const char *nl;
124
125         if (item->object.parsed)
126                 return 0;
127         item->object.parsed = 1;
128
129         if (size < 64)
130                 return -1;
131         if (memcmp("object ", bufptr, 7) || get_sha1_hex(bufptr + 7, sha1) || bufptr[47] != '\n')
132                 return -1;
133         bufptr += 48; /* "object " + sha1 + "\n" */
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 = &lookup_blob(sha1)->object;
147         } else if (!strcmp(type, tree_type)) {
148                 item->tagged = &lookup_tree(sha1)->object;
149         } else if (!strcmp(type, commit_type)) {
150                 item->tagged = &lookup_commit(sha1)->object;
151         } else if (!strcmp(type, tag_type)) {
152                 item->tagged = &lookup_tag(sha1)->object;
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_sha1_file(item->object.oid.hash, &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 }