Skip to content

Commit 08a4590

Browse files
ebiedermgitster
authored andcommitted
object-file-convert: convert commits that embed signed tags
As mentioned in the hash function transition plan commit mergetag lines need to be handled. The commit mergetag lines embed an entire tag object in a commit object. Keep the implementation sane if not fast by unembedding the tag object, converting the tag object, and embedding the new tag object, in the new commit object. In the long run I don't expect any other approach is maintainable, as tag objects may be extended in ways that require additional translation. To keep the implementation of convert_commit_object maintainable I have modified convert_commit_object to process the lines in any order, and to fail on unknown lines. We can't know ahead of time if a new line might embed something that needs translation or not so it is better to fail and require the code to be updated instead of silently mistranslating objects. Signed-off-by: Eric W. Biederman <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 318b023 commit 08a4590

File tree

1 file changed

+82
-22
lines changed

1 file changed

+82
-22
lines changed

object-file-convert.c

Lines changed: 82 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -146,35 +146,95 @@ static int convert_commit_object(struct strbuf *out,
146146
const int tree_entry_len = from->hexsz + 5;
147147
const int parent_entry_len = from->hexsz + 7;
148148
struct object_id oid, mapped_oid;
149-
const char *p;
149+
const char *p, *eol;
150150

151151
tail += size;
152-
if (tail <= bufptr + tree_entry_len + 1 || memcmp(bufptr, "tree ", 5) ||
153-
bufptr[tree_entry_len] != '\n')
154-
return error("bogus commit object");
155-
if (parse_oid_hex_algop(bufptr + 5, &oid, &p, from) < 0)
156-
return error("bad tree pointer");
157152

158-
if (repo_oid_to_algop(the_repository, &oid, to, &mapped_oid))
159-
return error("unable to map tree %s in commit object",
160-
oid_to_hex(&oid));
161-
strbuf_addf(out, "tree %s\n", oid_to_hex(&mapped_oid));
162-
bufptr = p + 1;
153+
while ((bufptr < tail) && (*bufptr != '\n')) {
154+
eol = memchr(bufptr, '\n', tail - bufptr);
155+
if (!eol)
156+
return error(_("bad %s in commit"), "line");
157+
158+
if (((bufptr + 5) < eol) && !memcmp(bufptr, "tree ", 5))
159+
{
160+
if (((bufptr + tree_entry_len) != eol) ||
161+
parse_oid_hex_algop(bufptr + 5, &oid, &p, from) ||
162+
(p != eol))
163+
return error(_("bad %s in commit"), "tree");
164+
165+
if (repo_oid_to_algop(the_repository, &oid, to, &mapped_oid))
166+
return error(_("unable to map %s %s in commit object"),
167+
"tree", oid_to_hex(&oid));
168+
strbuf_addf(out, "tree %s\n", oid_to_hex(&mapped_oid));
169+
}
170+
else if (((bufptr + 7) < eol) && !memcmp(bufptr, "parent ", 7))
171+
{
172+
if (((bufptr + parent_entry_len) != eol) ||
173+
parse_oid_hex_algop(bufptr + 7, &oid, &p, from) ||
174+
(p != eol))
175+
return error(_("bad %s in commit"), "parent");
163176

164-
while (bufptr + parent_entry_len < tail && !memcmp(bufptr, "parent ", 7)) {
165-
if (tail <= bufptr + parent_entry_len + 1 ||
166-
parse_oid_hex_algop(bufptr + 7, &oid, &p, from) ||
167-
*p != '\n')
168-
return error("bad parents in commit");
177+
if (repo_oid_to_algop(the_repository, &oid, to, &mapped_oid))
178+
return error(_("unable to map %s %s in commit object"),
179+
"parent", oid_to_hex(&oid));
169180

170-
if (repo_oid_to_algop(the_repository, &oid, to, &mapped_oid))
171-
return error("unable to map parent %s in commit object",
172-
oid_to_hex(&oid));
181+
strbuf_addf(out, "parent %s\n", oid_to_hex(&mapped_oid));
182+
}
183+
else if (((bufptr + 9) < eol) && !memcmp(bufptr, "mergetag ", 9))
184+
{
185+
struct strbuf tag = STRBUF_INIT, new_tag = STRBUF_INIT;
173186

174-
strbuf_addf(out, "parent %s\n", oid_to_hex(&mapped_oid));
175-
bufptr = p + 1;
187+
/* Recover the tag object from the mergetag */
188+
strbuf_add(&tag, bufptr + 9, (eol - (bufptr + 9)) + 1);
189+
190+
bufptr = eol + 1;
191+
while ((bufptr < tail) && (*bufptr == ' ')) {
192+
eol = memchr(bufptr, '\n', tail - bufptr);
193+
if (!eol) {
194+
strbuf_release(&tag);
195+
return error(_("bad %s in commit"), "mergetag continuation");
196+
}
197+
strbuf_add(&tag, bufptr + 1, (eol - (bufptr + 1)) + 1);
198+
bufptr = eol + 1;
199+
}
200+
201+
/* Compute the new tag object */
202+
if (convert_tag_object(&new_tag, from, to, tag.buf, tag.len)) {
203+
strbuf_release(&tag);
204+
strbuf_release(&new_tag);
205+
return -1;
206+
}
207+
208+
/* Write the new mergetag */
209+
strbuf_addstr(out, "mergetag");
210+
strbuf_add_lines(out, " ", new_tag.buf, new_tag.len);
211+
strbuf_release(&tag);
212+
strbuf_release(&new_tag);
213+
}
214+
else if (((bufptr + 7) < tail) && !memcmp(bufptr, "author ", 7))
215+
strbuf_add(out, bufptr, (eol - bufptr) + 1);
216+
else if (((bufptr + 10) < tail) && !memcmp(bufptr, "committer ", 10))
217+
strbuf_add(out, bufptr, (eol - bufptr) + 1);
218+
else if (((bufptr + 9) < tail) && !memcmp(bufptr, "encoding ", 9))
219+
strbuf_add(out, bufptr, (eol - bufptr) + 1);
220+
else if (((bufptr + 6) < tail) && !memcmp(bufptr, "gpgsig", 6))
221+
strbuf_add(out, bufptr, (eol - bufptr) + 1);
222+
else {
223+
/* Unknown line fail it might embed an oid */
224+
return -1;
225+
}
226+
/* Consume any trailing continuation lines */
227+
bufptr = eol + 1;
228+
while ((bufptr < tail) && (*bufptr == ' ')) {
229+
eol = memchr(bufptr, '\n', tail - bufptr);
230+
if (!eol)
231+
return error(_("bad %s in commit"), "continuation");
232+
strbuf_add(out, bufptr, (eol - bufptr) + 1);
233+
bufptr = eol + 1;
234+
}
176235
}
177-
strbuf_add(out, bufptr, tail - bufptr);
236+
if (bufptr < tail)
237+
strbuf_add(out, bufptr, tail - bufptr);
178238
return 0;
179239
}
180240

0 commit comments

Comments
 (0)