]> git.proxmox.com Git - libgit2.git/blame - src/tag.c
Merge branch 'timezone-offset' of https://github.com/nulltoken/libgit2 into timezone
[libgit2.git] / src / tag.c
CommitLineData
f8758044
VM
1/*
2 * This file is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License, version 2,
4 * as published by the Free Software Foundation.
5 *
6 * In addition to the permissions in the GNU General Public License,
7 * the authors give you unlimited permission to link the compiled
8 * version of this file into combinations with other programs,
9 * and to distribute those combinations without any restriction
10 * coming from the use of this file. (The General Public License
11 * restrictions do apply in other respects; for example, they cover
12 * modification of the file, and distribution when not linked into
13 * a combined executable.)
14 *
15 * This file is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; see the file COPYING. If not, write to
22 * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
23 * Boston, MA 02110-1301, USA.
24 */
25
26#include "common.h"
27#include "commit.h"
28#include "tag.h"
58519018 29#include "person.h"
f8758044 30#include "revwalk.h"
44908fe7
VM
31#include "git2/object.h"
32#include "git2/repository.h"
f8758044
VM
33
34void git_tag__free(git_tag *tag)
35{
58519018 36 git_person__free(tag->tagger);
f8758044
VM
37 free(tag->message);
38 free(tag->tag_name);
f8758044
VM
39 free(tag);
40}
41
d45b4a9a
VM
42const git_oid *git_tag_id(git_tag *c)
43{
44 return git_object_id((git_object *)c);
f8758044
VM
45}
46
f49a2e49 47const git_object *git_tag_target(git_tag *t)
f8758044 48{
58519018 49 assert(t);
f8758044
VM
50 return t->target;
51}
52
ec25391d
VM
53void git_tag_set_target(git_tag *tag, git_object *target)
54{
55 assert(tag && target);
56
57 tag->object.modified = 1;
58 tag->target = target;
59 tag->type = git_object_type(target);
60}
61
f8758044
VM
62git_otype git_tag_type(git_tag *t)
63{
58519018 64 assert(t);
f8758044
VM
65 return t->type;
66}
67
ec25391d
VM
68void git_tag_set_type(git_tag *tag, git_otype type)
69{
70 assert(tag);
71
72 tag->object.modified = 1;
73 tag->type = type;
74}
75
f8758044
VM
76const char *git_tag_name(git_tag *t)
77{
58519018 78 assert(t);
f8758044
VM
79 return t->tag_name;
80}
81
ec25391d
VM
82void git_tag_set_name(git_tag *tag, const char *name)
83{
84 assert(tag && name);
85
86 /* TODO: sanity check? no newlines in message */
87 tag->object.modified = 1;
88
89 if (tag->tag_name)
90 free(tag->tag_name);
91
92 tag->tag_name = git__strdup(name);
93}
94
f8758044
VM
95const git_person *git_tag_tagger(git_tag *t)
96{
f8758044
VM
97 return t->tagger;
98}
99
13710f1e 100void git_tag_set_tagger(git_tag *tag, const char *name, const char *email, time_t time, int offset)
ec25391d 101{
58519018 102 assert(tag && name && email);
ec25391d 103 tag->object.modified = 1;
ec25391d 104
58519018 105 git_person__free(tag->tagger);
13710f1e 106 tag->tagger = git_person__new(name, email, time, offset);
ec25391d
VM
107}
108
f8758044
VM
109const char *git_tag_message(git_tag *t)
110{
58519018 111 assert(t);
f8758044
VM
112 return t->message;
113}
114
ec25391d
VM
115void git_tag_set_message(git_tag *tag, const char *message)
116{
117 assert(tag && message);
118
119 tag->object.modified = 1;
120
121 if (tag->message)
122 free(tag->message);
123
124 tag->message = git__strdup(message);
125}
126
f8758044
VM
127static int parse_tag_buffer(git_tag *tag, char *buffer, const char *buffer_end)
128{
129 static const char *tag_types[] = {
130 NULL, "commit\n", "tree\n", "blob\n", "tag\n"
131 };
132
133 git_oid target_oid;
134 unsigned int i, text_len;
135 char *search;
1795f879 136 int error;
f8758044 137
1795f879
VM
138 if ((error = git__parse_oid(&target_oid, &buffer, buffer_end, "object ")) < 0)
139 return error;
f8758044
VM
140
141 if (buffer + 5 >= buffer_end)
142 return GIT_EOBJCORRUPTED;
143
144 if (memcmp(buffer, "type ", 5) != 0)
145 return GIT_EOBJCORRUPTED;
146 buffer += 5;
147
148 tag->type = GIT_OBJ_BAD;
149
150 for (i = 1; i < ARRAY_SIZE(tag_types); ++i) {
151 size_t type_length = strlen(tag_types[i]);
152
153 if (buffer + type_length >= buffer_end)
154 return GIT_EOBJCORRUPTED;
155
156 if (memcmp(buffer, tag_types[i], type_length) == 0) {
157 tag->type = i;
158 buffer += type_length;
159 break;
160 }
161 }
162
163 if (tag->type == GIT_OBJ_BAD)
164 return GIT_EOBJCORRUPTED;
165
1795f879
VM
166 error = git_repository_lookup(&tag->target, tag->object.repo, &target_oid, tag->type);
167 if (error < 0)
168 return error;
f8758044
VM
169
170 if (buffer + 4 >= buffer_end)
171 return GIT_EOBJCORRUPTED;
172
173 if (memcmp(buffer, "tag ", 4) != 0)
174 return GIT_EOBJCORRUPTED;
175 buffer += 4;
176
177 search = memchr(buffer, '\n', buffer_end - buffer);
178 if (search == NULL)
179 return GIT_EOBJCORRUPTED;
180
181 text_len = search - buffer;
182
183 if (tag->tag_name != NULL)
184 free(tag->tag_name);
185
186 tag->tag_name = git__malloc(text_len + 1);
187 memcpy(tag->tag_name, buffer, text_len);
188 tag->tag_name[text_len] = '\0';
189
190 buffer = search + 1;
191
192 if (tag->tagger != NULL)
58519018 193 git_person__free(tag->tagger);
f8758044
VM
194
195 tag->tagger = git__malloc(sizeof(git_person));
196
1795f879
VM
197 if ((error = git_person__parse(tag->tagger, &buffer, buffer_end, "tagger ")) != 0)
198 return error;
f8758044 199
ec25391d 200 text_len = buffer_end - ++buffer;
f8758044
VM
201
202 if (tag->message != NULL)
203 free(tag->message);
204
205 tag->message = git__malloc(text_len + 1);
206 memcpy(tag->message, buffer, text_len);
207 tag->message[text_len] = '\0';
208
6f02c3ba 209 return GIT_SUCCESS;
f8758044
VM
210}
211
ec25391d
VM
212int git_tag__writeback(git_tag *tag, git_odb_source *src)
213{
214 if (tag->target == NULL || tag->tag_name == NULL || tag->tagger == NULL)
1795f879 215 return GIT_EMISSINGOBJDATA;
ec25391d
VM
216
217 git__write_oid(src, "object", git_object_id(tag->target));
d12299fe 218 git__source_printf(src, "type %s\n", git_object_type2string(tag->type));
ec25391d 219 git__source_printf(src, "tag %s\n", tag->tag_name);
58519018 220 git_person__write(src, "tagger", tag->tagger);
ec25391d
VM
221
222 if (tag->message != NULL)
223 git__source_printf(src, "\n%s", tag->message);
224
225 return GIT_SUCCESS;
226}
227
228
f8758044
VM
229int git_tag__parse(git_tag *tag)
230{
58519018 231 assert(tag && tag->object.source.open);
6b1eab39 232 return parse_tag_buffer(tag, tag->object.source.raw.data, (char *)tag->object.source.raw.data + tag->object.source.raw.len);
f8758044
VM
233}
234