object-file-convert: convert commit objects when writing
When writing a commit object in a repository with both SHA-1 and SHA-256, we'll need to convert our commit objects so that we can write the hash values for both into the repository. To do so, let's add a function to convert commit objects. Read the commit object and map the tree value and any of the parent values, and copy the rest of the commit through unmodified. Note that we don't need to modify the signature headers, because they are the same under both algorithms. Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
brian m. carlson committed
Oct 1, 2023 at 21:40 UTC
318b023e4a3f5e4f2ecf202aa87db7e5df2c4442
1 file changed
+45
-1
object-file-convert.c
+45
-1
@@ -136,6 +136,48 @@ static int convert_tag_object(struct strbuf *out,
136
return 0;
137
}
138
139
+static int convert_commit_object(struct strbuf *out,
140
+ const struct git_hash_algo *from,
141
+ const struct git_hash_algo *to,
142
+ const char *buffer, size_t size)
143
+{
144
+ const char *tail = buffer;
145
+ const char *bufptr = buffer;
146
+ const int tree_entry_len = from->hexsz + 5;
147
+ const int parent_entry_len = from->hexsz + 7;
148
+ struct object_id oid, mapped_oid;
149
+ const char *p;
150
+
151
+ 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");
157
+
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;
163
+
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");
169
+
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));
173
+
174
+ strbuf_addf(out, "parent %s\n", oid_to_hex(&mapped_oid));
175
+ bufptr = p + 1;
176
+ }
177
+ strbuf_add(out, bufptr, tail - bufptr);
178
+ return 0;
179
+}
180
+
181
int convert_object_file(struct strbuf *outbuf,
182
const struct git_hash_algo *from,
183
const struct git_hash_algo *to,
@@ -150,13 +192,15 @@ int convert_object_file(struct strbuf *outbuf,
192
BUG("Refusing noop object file conversion");
193
194
switch (type) {
195
+ case OBJ_COMMIT:
196
+ ret = convert_commit_object(outbuf, from, to, buf, len);
197
+ break;
198
case OBJ_TREE:
199
ret = convert_tree_object(outbuf, from, to, buf, len);
200
break;
201
case OBJ_TAG:
202
ret = convert_tag_object(outbuf, from, to, buf, len);
203
break;
159
- case OBJ_COMMIT:
204
default:
205
/* Not implemented yet, so fail. */
206
ret = -1;