aboutsummaryrefslogtreecommitdiffstats
path: root/object-file-convert.c
diff options
context:
space:
mode:
authorbrian m. carlson <sandals@crustytoothpaste.net>2023-10-01 21:40:19 -0500
committerJunio C Hamano <gitster@pobox.com>2023-10-02 14:57:39 -0700
commit33a14e81ae0673f8b3f7cf85168c7c573fa2fb58 (patch)
treed27d33812f0842331dc4e9e799301f0e6374ff2a /object-file-convert.c
parent45b3b1214154975ac03c818838e3d12571f57d1e (diff)
downloadgit-33a14e81ae0673f8b3f7cf85168c7c573fa2fb58.tar.gz
object-file-convert: add a function to convert trees between algorithms
In the future, we're going to want to provide SHA-256 repositories that have compatibility support for SHA-1 as well. In order to do so, we'll need to be able to convert tree objects from SHA-256 to SHA-1 by writing a tree with each SHA-256 object ID mapped to a SHA-1 object ID. We implement a function, convert_tree_object, that takes an existing tree buffer and writes it to a new strbuf, converting between algorithms. Let's make this function generic, because while we only need it to convert from the main algorithm to the compatibility algorithm now, we may need to do the other way around in the future, such as for transport. We avoid reusing the code in decode_tree_entry because that code normalizes data, and we don't want that here. We want to produce a complete round trip of data, so if, for example, the old entry had a wrongly zero-padded mode, we'd want to preserve that when converting to ensure a stable hash value. 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>
Diffstat (limited to 'object-file-convert.c')
-rw-r--r--object-file-convert.c51
1 files changed, 50 insertions, 1 deletions
diff --git a/object-file-convert.c b/object-file-convert.c
index 1ec945eaa1..70b80fb61e 100644
--- a/object-file-convert.c
+++ b/object-file-convert.c
@@ -1,8 +1,10 @@
#include "git-compat-util.h"
#include "gettext.h"
#include "strbuf.h"
+#include "hex.h"
#include "repository.h"
#include "hash-ll.h"
+#include "hash.h"
#include "object.h"
#include "loose.h"
#include "object-file-convert.h"
@@ -36,6 +38,51 @@ int repo_oid_to_algop(struct repository *repo, const struct object_id *src,
return 0;
}
+static int decode_tree_entry_raw(struct object_id *oid, const char **path,
+ size_t *len, const struct git_hash_algo *algo,
+ const char *buf, unsigned long size)
+{
+ uint16_t mode;
+ const unsigned hashsz = algo->rawsz;
+
+ if (size < hashsz + 3 || buf[size - (hashsz + 1)]) {
+ return -1;
+ }
+
+ *path = parse_mode(buf, &mode);
+ if (!*path || !**path)
+ return -1;
+ *len = strlen(*path) + 1;
+
+ oidread_algop(oid, (const unsigned char *)*path + *len, algo);
+ return 0;
+}
+
+static int convert_tree_object(struct strbuf *out,
+ const struct git_hash_algo *from,
+ const struct git_hash_algo *to,
+ const char *buffer, size_t size)
+{
+ const char *p = buffer, *end = buffer + size;
+
+ while (p < end) {
+ struct object_id entry_oid, mapped_oid;
+ const char *path = NULL;
+ size_t pathlen;
+
+ if (decode_tree_entry_raw(&entry_oid, &path, &pathlen, from, p,
+ end - p))
+ return error(_("failed to decode tree entry"));
+ if (repo_oid_to_algop(the_repository, &entry_oid, to, &mapped_oid))
+ return error(_("failed to map tree entry for %s"), oid_to_hex(&entry_oid));
+ strbuf_add(out, p, path - p);
+ strbuf_add(out, path, pathlen);
+ strbuf_add(out, mapped_oid.hash, to->rawsz);
+ p = path + pathlen + from->rawsz;
+ }
+ return 0;
+}
+
int convert_object_file(struct strbuf *outbuf,
const struct git_hash_algo *from,
const struct git_hash_algo *to,
@@ -50,8 +97,10 @@ int convert_object_file(struct strbuf *outbuf,
BUG("Refusing noop object file conversion");
switch (type) {
- case OBJ_COMMIT:
case OBJ_TREE:
+ ret = convert_tree_object(outbuf, from, to, buf, len);
+ break;
+ case OBJ_COMMIT:
case OBJ_TAG:
default:
/* Not implemented yet, so fail. */