]>
Commit | Line | Data |
---|---|---|
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 | |
34 | void 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 |
42 | const git_oid *git_tag_id(git_tag *c) |
43 | { | |
44 | return git_object_id((git_object *)c); | |
f8758044 VM |
45 | } |
46 | ||
f49a2e49 | 47 | const git_object *git_tag_target(git_tag *t) |
f8758044 | 48 | { |
58519018 | 49 | assert(t); |
f8758044 VM |
50 | return t->target; |
51 | } | |
52 | ||
ec25391d VM |
53 | void 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 |
62 | git_otype git_tag_type(git_tag *t) |
63 | { | |
58519018 | 64 | assert(t); |
f8758044 VM |
65 | return t->type; |
66 | } | |
67 | ||
ec25391d VM |
68 | void 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 |
76 | const char *git_tag_name(git_tag *t) |
77 | { | |
58519018 | 78 | assert(t); |
f8758044 VM |
79 | return t->tag_name; |
80 | } | |
81 | ||
ec25391d VM |
82 | void 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 |
95 | const git_person *git_tag_tagger(git_tag *t) |
96 | { | |
f8758044 VM |
97 | return t->tagger; |
98 | } | |
99 | ||
13710f1e | 100 | void 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 |
109 | const char *git_tag_message(git_tag *t) |
110 | { | |
58519018 | 111 | assert(t); |
f8758044 VM |
112 | return t->message; |
113 | } | |
114 | ||
ec25391d VM |
115 | void 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 |
127 | static 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 |
212 | int 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 |
229 | int 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 |