Download raw body.
initial sha256 support in the network protocol
The "big" diff finally!
In the end I haven't managed to split it in smaller pieces since both
fetch and send changes depends on the changes I'm doing to gitproto.
Hopefully, it's not too big to review ;-)
There's some leftovers/spoilers on how I was planning to handle clone.
The idea would be to pass -1 for the protocol, and have fetch tell us
what the server supports. It's still a bit tricky because we have to
change the fetch_progress callback and reinitialize some state after
the capabilities are parsed. This is left for later.
Another point, I could add object-format=sha1 capability to both send
and fetch, as git does, but felt unneeded since sha1 is the default
behaviour.
commit c1a7f0d0a8990dbb75d878652418753711ddd47c (main)
from: Omar Polo <op@omarpolo.com>
date: Sat Feb 7 17:00:17 2026 UTC
initial sha256 support in the network protocol
fetch and send to/from sha256 repositories now actually works. many
thanks to runxiyu on irc for making me realize that we don't actually
need to support the Git protocol v2 for sha256, but just enable the
capability, which is what this diff does.
Clone still needs work. For now, a workaround is to create an empty
sha256 repository locally, add the remote and fetch instead.
No regress test enabled yet since they all depend on clone to work.
M lib/fetch.c | 19+ 11-
M lib/gitproto.c | 17+ 3-
M lib/got_lib_gitproto.h | 4+ 1-
M lib/got_lib_privsep.h | 5+ 3-
M lib/privsep.c | 7+ 6-
M lib/send.c | 2+ 5-
M libexec/got-fetch-pack/got-fetch-pack.c | 50+ 39-
M libexec/got-send-pack/got-send-pack.c | 18+ 11-
8 files changed, 122 insertions(+), 79 deletions(-)
commit - cc8eaf00fec74bd43bc96a5daedef4c8540964bf
commit + c1a7f0d0a8990dbb75d878652418753711ddd47c
blob - f271143b425954027040e9e3e0ad142fb6c4d327
blob + b78727982872932c8a61d31ef72455d7c93c4b63
--- lib/fetch.c
+++ lib/fetch.c
@@ -135,15 +135,13 @@ got_fetch_pack(struct got_object_id **pack_hash, struc
uint32_t nobj = 0;
char *path;
char *progress = NULL;
+ enum got_hash_algorithm algo = GOT_HASH_SHA1;
+ size_t idlen;
*pack_hash = NULL;
memset(&fetchibuf, 0, sizeof(fetchibuf));
memset(&idxibuf, 0, sizeof(idxibuf));
- if (repo && got_repo_get_object_format(repo) != GOT_HASH_SHA1)
- return got_error_fmt(GOT_ERR_NOT_IMPL,
- "sha256 object IDs unsupported in network protocol");
-
/*
* Prevent fetching of references that won't make any
* sense outside of the remote repository's context.
@@ -157,7 +155,13 @@ got_fetch_pack(struct got_object_id **pack_hash, struc
return got_error_path(refname, GOT_ERR_FETCH_BAD_REF);
}
+ /* for listing refs we don't actually care about the algorithm */
if (!list_refs_only)
+ algo = got_repo_get_object_format(repo);
+
+ idlen = got_hash_digest_length(algo);
+
+ if (!list_refs_only)
repo_path = got_repo_get_path_git_dir(repo);
for (i = 0; i < nitems(tmpfds); i++)
@@ -195,7 +199,6 @@ got_fetch_pack(struct got_object_id **pack_hash, struc
free(refname);
free(id);
}
-
}
if (list_refs_only) {
@@ -282,7 +285,7 @@ got_fetch_pack(struct got_object_id **pack_hash, struc
err = got_error_from_errno("dup");
goto done;
}
- err = got_privsep_send_fetch_req(&fetchibuf, nfetchfd, &have_refs,
+ err = got_privsep_send_fetch_req(&fetchibuf, nfetchfd, algo, &have_refs,
fetch_all_branches, wanted_branches, wanted_refs,
list_refs_only, worktree_refname, remote_head, no_head, verbosity);
if (err != NULL)
@@ -319,11 +322,11 @@ got_fetch_pack(struct got_object_id **pack_hash, struc
err = got_privsep_recv_fetch_progress(&done,
&id, &refname, symrefs, &server_progress,
- &packfile_size_cur, (*pack_hash)->hash, &fetchibuf);
+ &packfile_size_cur, *pack_hash, &fetchibuf);
if (err != NULL)
goto done;
/* Don't report size progress for an empty pack file. */
- if (packfile_size_cur <= ssizeof(pack_hdr) + SHA1_DIGEST_LENGTH)
+ if (packfile_size_cur <= ssizeof(pack_hdr) + idlen)
packfile_size_cur = 0;
if (!done && refname && id) {
err = got_pathlist_insert(&pe, refs, refname, id);
@@ -394,12 +397,17 @@ got_fetch_pack(struct got_object_id **pack_hash, struc
goto done;
}
+ if ((*pack_hash)->algo != algo) {
+ err = got_error(GOT_ERR_OBJECT_FORMAT);
+ goto done;
+ }
+
/* If zero data was fetched without error we are already up-to-date. */
if (packfile_size == 0) {
free(*pack_hash);
*pack_hash = NULL;
goto done;
- } else if (packfile_size < ssizeof(pack_hdr) + SHA1_DIGEST_LENGTH) {
+ } else if (packfile_size < ssizeof(pack_hdr) + idlen) {
err = got_error_msg(GOT_ERR_BAD_PACKFILE, "short pack file");
goto done;
} else {
@@ -426,13 +434,13 @@ got_fetch_pack(struct got_object_id **pack_hash, struc
}
nobj = be32toh(pack_hdr.nobjects);
if (nobj == 0 &&
- packfile_size > ssizeof(pack_hdr) + SHA1_DIGEST_LENGTH) {
+ packfile_size > ssizeof(pack_hdr) + idlen) {
err = got_error_msg(GOT_ERR_BAD_PACKFILE,
"bad pack file with zero objects");
goto done;
}
if (nobj != 0 &&
- packfile_size <= ssizeof(pack_hdr) + SHA1_DIGEST_LENGTH) {
+ packfile_size <= ssizeof(pack_hdr) + idlen) {
err = got_error_msg(GOT_ERR_BAD_PACKFILE,
"empty pack file with non-zero object count");
goto done;
blob - f8a58e05685c1a15956029d0833c3014e3008d78
blob + f63af5151c343acd415e881e2ef503a4471825b0
--- lib/gitproto.c
+++ lib/gitproto.c
@@ -23,9 +23,12 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sha1.h>
+#include <sha2.h>
#include "got_error.h"
#include "got_path.h"
+#include "got_object.h"
#include "got_lib_gitproto.h"
@@ -229,7 +232,7 @@ got_gitproto_parse_ref_update_line(char **old_id_str,
static const struct got_error *
match_capability(char **my_capabilities, const char *capa,
- const struct got_capability *mycapa)
+ const struct got_capability *mycapa, enum got_hash_algorithm *algo)
{
char *equalsign;
char *s;
@@ -238,6 +241,15 @@ match_capability(char **my_capabilities, const char *c
if (equalsign) {
if (strncmp(capa, mycapa->key, equalsign - capa) != 0)
return NULL;
+
+ if (strcmp(mycapa->key, "object-format") == 0) {
+ /* require an exact match on object-format value */
+ if (strcmp(equalsign + 1, mycapa->value) != 0)
+ return NULL;
+
+ if (strcmp(mycapa->value, "sha256") == 0)
+ *algo = GOT_HASH_SHA256;
+ }
} else {
if (strcmp(capa, mycapa->key) != 0)
return NULL;
@@ -296,13 +308,15 @@ done:
const struct got_error *
got_gitproto_match_capabilities(char **common_capabilities,
struct got_pathlist_head *symrefs, char *capabilities,
- const struct got_capability my_capabilities[], size_t ncapa)
+ const struct got_capability my_capabilities[], size_t ncapa,
+ enum got_hash_algorithm *algo)
{
const struct got_error *err = NULL;
char *capa, *equalsign;
size_t i;
*common_capabilities = NULL;
+ *algo = GOT_HASH_SHA1;
do {
capa = strsep(&capabilities, " ");
if (capa == NULL)
@@ -319,7 +333,7 @@ got_gitproto_match_capabilities(char **common_capabili
for (i = 0; i < ncapa; i++) {
err = match_capability(common_capabilities,
- capa, &my_capabilities[i]);
+ capa, &my_capabilities[i], algo);
if (err)
break;
}
blob - 09426d878e3a3c32836fe6d798cf82b8f46702e5
blob + 6128c320387d0fc02ee3b1edf54f6d59de13bb86
--- lib/got_lib_gitproto.h
+++ lib/got_lib_gitproto.h
@@ -21,6 +21,7 @@
#define GOT_CAPA_REPORT_STATUS "report-status"
#define GOT_CAPA_DELETE_REFS "delete-refs"
#define GOT_CAPA_NO_THIN "no-thin"
+#define GOT_CAPA_OBJECT_FORMAT "object-format"
#define GOT_SIDEBAND_PACKFILE_DATA 1
#define GOT_SIDEBAND_PROGRESS_INFO 2
@@ -34,6 +35,7 @@ struct got_capability {
};
struct got_pathlist_head;
+enum got_hash_algorithm;
const struct got_error *got_gitproto_parse_refline(char **id_str,
char **refname, char **server_capabilities, char *line, int len);
@@ -47,7 +49,8 @@ const struct got_error *got_gitproto_parse_ref_update_
const struct got_error *got_gitproto_match_capabilities(
char **common_capabilities,
struct got_pathlist_head *symrefs, char *capabilities,
- const struct got_capability my_capabilities[], size_t ncapa);
+ const struct got_capability my_capabilities[], size_t ncapa,
+ enum got_hash_algorithm *);
const struct got_error *got_gitproto_append_capabilities(size_t *capalen,
char *buf, size_t offset, size_t bufsize,
const struct got_capability my_capabilities[], size_t ncapa);
blob - bee307699142e88ce12f0d346090e26d9b6238d3
blob + 6d1e35b9cd6137e782e25a9f4f3a66450cb77a7e
--- lib/got_lib_privsep.h
+++ lib/got_lib_privsep.h
@@ -405,6 +405,7 @@ struct got_imsg_fetch_wanted_ref {
/* Structure for GOT_IMSG_FETCH_REQUEST data. */
struct got_imsg_fetch_request {
+ int expected_algo; /* -1 for unknown */
int no_head;
int fetch_all_branches;
int list_refs_only;
@@ -452,6 +453,7 @@ struct got_imsg_fetch_download_progress {
/* Structure for GOT_IMSG_SEND_REQUEST data. */
struct got_imsg_send_request {
+ int algo;
int verbosity;
size_t nrefs;
/* Followed by nrefs GOT_IMSG_SEND_REF messages. */
@@ -721,14 +723,14 @@ const struct got_error *got_privsep_send_index_pack_ou
int);
const struct got_error *got_privsep_recv_index_progress(int *, int *, int *,
int *, int *, struct imsgbuf *ibuf);
-const struct got_error *got_privsep_send_fetch_req(struct imsgbuf *, int,
+const struct got_error *got_privsep_send_fetch_req(struct imsgbuf *, int, int,
struct got_pathlist_head *, int, struct got_pathlist_head *,
struct got_pathlist_head *, int, const char *, const char *, int, int);
const struct got_error *got_privsep_send_fetch_outfd(struct imsgbuf *, int);
const struct got_error *got_privsep_recv_fetch_progress(int *,
struct got_object_id **, char **, struct got_pathlist_head *, char **,
- off_t *, uint8_t *, struct imsgbuf *);
-const struct got_error *got_privsep_send_send_req(struct imsgbuf *, int,
+ off_t *, struct got_object_id *, struct imsgbuf *);
+const struct got_error *got_privsep_send_send_req(struct imsgbuf *, int, int,
struct got_pathlist_head *, struct got_pathlist_head *, int);
const struct got_error *got_privsep_recv_send_remote_refs(
struct got_pathlist_head *, struct imsgbuf *);
blob - e580803b5171ab0806bd69d4818151fa6fdd24af
blob + 8f1d693232a9d8b268ee215889b827c3ea255cce
--- lib/privsep.c
+++ lib/privsep.c
@@ -553,7 +553,7 @@ got_privsep_send_obj(struct imsgbuf *ibuf, struct got_
}
const struct got_error *
-got_privsep_send_fetch_req(struct imsgbuf *ibuf, int fd,
+got_privsep_send_fetch_req(struct imsgbuf *ibuf, int fd, int expected_algo,
struct got_pathlist_head *have_refs, int fetch_all_branches,
struct got_pathlist_head *wanted_branches,
struct got_pathlist_head *wanted_refs, int list_refs_only,
@@ -588,6 +588,7 @@ got_privsep_send_fetch_req(struct imsgbuf *ibuf, int f
}
memset(&fetchreq, 0, sizeof(fetchreq));
+ fetchreq.expected_algo = expected_algo;
fetchreq.no_head = no_head;
fetchreq.fetch_all_branches = fetch_all_branches;
fetchreq.list_refs_only = list_refs_only;
@@ -713,7 +714,7 @@ got_privsep_send_fetch_outfd(struct imsgbuf *ibuf, int
const struct got_error *
got_privsep_recv_fetch_progress(int *done, struct got_object_id **id,
char **refname, struct got_pathlist_head *symrefs, char **server_progress,
- off_t *packfile_size, uint8_t *pack_sha1, struct imsgbuf *ibuf)
+ off_t *packfile_size, struct got_object_id *pack_hash, struct imsgbuf *ibuf)
{
const struct got_error *err = NULL;
struct imsg imsg;
@@ -729,7 +730,7 @@ got_privsep_recv_fetch_progress(int *done, struct got_
*refname = NULL;
*server_progress = NULL;
*packfile_size = 0;
- memset(pack_sha1, 0, SHA1_DIGEST_LENGTH);
+ memset(pack_hash, 0, sizeof(*pack_hash));
err = got_privsep_recv_imsg(&imsg, ibuf, 0);
if (err)
@@ -838,11 +839,10 @@ got_privsep_recv_fetch_progress(int *done, struct got_
memcpy(packfile_size, imsg.data, sizeof(*packfile_size));
break;
case GOT_IMSG_FETCH_DONE:
- if (datalen != SHA1_DIGEST_LENGTH) {
+ if (imsg_get_data(&imsg, pack_hash, sizeof(*pack_hash)) == -1) {
err = got_error(GOT_ERR_PRIVSEP_MSG);
break;
}
- memcpy(pack_sha1, imsg.data, SHA1_DIGEST_LENGTH);
*done = 1;
break;
default:
@@ -887,7 +887,7 @@ send_send_ref(const char *name, size_t name_len, struc
}
const struct got_error *
-got_privsep_send_send_req(struct imsgbuf *ibuf, int fd,
+got_privsep_send_send_req(struct imsgbuf *ibuf, int fd, int algo,
struct got_pathlist_head *have_refs,
struct got_pathlist_head *delete_refs,
int verbosity)
@@ -899,6 +899,7 @@ got_privsep_send_send_req(struct imsgbuf *ibuf, int fd
memset(&zero_id, 0, sizeof(zero_id));
memset(&sendreq, 0, sizeof(sendreq));
+ sendreq.algo = algo;
sendreq.verbosity = verbosity;
RB_FOREACH(pe, got_pathlist_head, have_refs)
sendreq.nrefs++;
blob - 90efc87ae3b506ea594098e26225608af3b9d3f6
blob + 0eac9087300aecab278935e6f77f60478627b47a
--- lib/send.c
+++ lib/send.c
@@ -367,10 +367,6 @@ got_send_pack(const char *remote_name, struct got_path
memset(&sendibuf, 0, sizeof(sendibuf));
- if (got_repo_get_object_format(repo) != GOT_HASH_SHA1)
- return got_error_fmt(GOT_ERR_NOT_IMPL,
- "sha256 object IDs unsupported in network protocol");
-
RB_FOREACH(pe, got_pathlist_head, branch_names) {
const char *branchname = pe->path;
const char *targetname = pe->data;
@@ -500,7 +496,8 @@ got_send_pack(const char *remote_name, struct got_path
nours++;
}
- err = got_privsep_send_send_req(&sendibuf, nsendfd, &have_refs,
+ err = got_privsep_send_send_req(&sendibuf, nsendfd,
+ got_repo_get_object_format(repo), &have_refs,
delete_branches, verbosity);
if (err)
goto done;
blob - 8185109b334df44388594704fe45a9e7de47bbf4
blob + ef7f20aedafd9c0d532e4b464943c35f2f88b582
--- libexec/got-fetch-pack/got-fetch-pack.c
+++ libexec/got-fetch-pack/got-fetch-pack.c
@@ -69,19 +69,21 @@ static int chattygot;
static const struct got_capability got_capabilities[] = {
{ GOT_CAPA_AGENT, "got/" GOT_VERSION_STR },
+ { GOT_CAPA_OBJECT_FORMAT, "sha256" },
{ GOT_CAPA_OFS_DELTA, NULL },
{ GOT_CAPA_SIDE_BAND_64K, NULL },
};
static void
match_remote_ref(struct got_pathlist_head *have_refs,
- struct got_object_id *my_id, const char *refname)
+ struct got_object_id *my_id, const char *refname, int algo)
{
struct got_pathlist_entry *pe;
/* XXX zero-hash signifies we don't have this ref;
* we should use a flag instead */
memset(my_id, 0, sizeof(*my_id));
+ my_id->algo = algo;
RB_FOREACH(pe, got_pathlist_head, have_refs) {
struct got_object_id *id = pe->data;
@@ -170,10 +172,10 @@ send_fetch_download_progress(struct imsgbuf *ibuf, off
}
static const struct got_error *
-send_fetch_done(struct imsgbuf *ibuf, uint8_t *pack_sha1)
+send_fetch_done(struct imsgbuf *ibuf, struct got_object_id *pack_hash)
{
if (imsg_compose(ibuf, GOT_IMSG_FETCH_DONE, 0, 0, -1,
- pack_sha1, SHA1_DIGEST_LENGTH) == -1)
+ pack_hash, sizeof(*pack_hash)) == -1)
return got_error_from_errno("imsg_compose FETCH");
return got_privsep_flush_imsg(ibuf);
}
@@ -299,17 +301,17 @@ send_fetch_ref(struct imsgbuf *ibuf, struct got_object
static const struct got_error *
fetch_ref(struct imsgbuf *ibuf, struct got_pathlist_head *have_refs,
struct got_object_id *have, struct got_object_id *want,
- const char *refname, const char *id_str)
+ const char *refname, const char *id_str, int algo)
{
const struct got_error *err;
char *theirs = NULL, *mine = NULL;
- if (!got_parse_object_id(want, id_str, GOT_HASH_SHA1)) {
+ if (!got_parse_object_id(want, id_str, algo)) {
err = got_error(GOT_ERR_BAD_OBJ_ID_STR);
goto done;
}
- match_remote_ref(have_refs, have, refname);
+ match_remote_ref(have_refs, have, refname, algo);
err = send_fetch_ref(ibuf, want, refname);
if (err)
goto done;
@@ -334,7 +336,8 @@ done:
}
static const struct got_error *
-fetch_pack(int fd, int packfd, uint8_t *pack_sha1,
+fetch_pack(int fd, int packfd, int expected_algo,
+ struct got_object_id *pack_hash,
struct got_pathlist_head *have_refs, int fetch_all_branches,
struct got_pathlist_head *wanted_branches,
struct got_pathlist_head *wanted_refs, int list_refs_only,
@@ -343,7 +346,7 @@ fetch_pack(int fd, int packfd, uint8_t *pack_sha1,
{
const struct got_error *err = NULL;
char buf[GOT_PKT_MAX];
- char hashstr[SHA1_DIGEST_STRING_LENGTH];
+ char hashstr[GOT_HASH_DIGEST_STRING_MAXLEN];
struct got_object_id *have, *want;
int is_firstpkt = 1, nref = 0, refsz = 16;
int i, n, nwant = 0, nhave = 0, acked = 0, eof = 0;
@@ -357,13 +360,14 @@ fetch_pack(int fd, int packfd, uint8_t *pack_sha1,
int sent_my_capabilites = 0, have_sidebands = 0;
int found_branch = 0;
struct got_hash ctx;
- uint8_t sha1_buf[SHA1_DIGEST_LENGTH];
+ uint8_t sha1_buf[GOT_HASH_DIGEST_MAXLEN];
size_t sha1_buf_len = 0;
ssize_t w;
struct got_ratelimit rl;
+ size_t idlen;
+ enum got_hash_algorithm algo = GOT_HASH_SHA1;
RB_INIT(&symrefs);
- got_hash_init(&ctx, GOT_HASH_SHA1);
got_ratelimit_init(&rl, 0, 500);
have = malloc(refsz * sizeof(have[0]));
@@ -416,9 +420,13 @@ fetch_pack(int fd, int packfd, uint8_t *pack_sha1,
getprogname(), server_capabilities);
err = got_gitproto_match_capabilities(&my_capabilities,
&symrefs, server_capabilities,
- got_capabilities, nitems(got_capabilities));
+ got_capabilities, nitems(got_capabilities), &algo);
if (err)
goto done;
+ if (expected_algo != -1 && algo != expected_algo) {
+ err = got_error(GOT_ERR_OBJECT_FORMAT);
+ goto done;
+ }
if (chattygot)
fprintf(stderr, "%s: my capabilities:%s\n",
getprogname(), my_capabilities != NULL ?
@@ -477,14 +485,14 @@ fetch_pack(int fd, int packfd, uint8_t *pack_sha1,
if (list_refs_only || strncmp(refname, "refs/tags/", 10) == 0) {
err = fetch_ref(ibuf, have_refs, &have[nref],
- &want[nref], refname, id_str);
+ &want[nref], refname, id_str, algo);
if (err)
goto done;
nref++;
} else if (strncmp(refname, "refs/heads/", 11) == 0) {
if (fetch_all_branches) {
err = fetch_ref(ibuf, have_refs, &have[nref],
- &want[nref], refname, id_str);
+ &want[nref], refname, id_str, algo);
if (err)
goto done;
nref++;
@@ -498,7 +506,7 @@ fetch_pack(int fd, int packfd, uint8_t *pack_sha1,
if (pe != NULL || (worktree_branch != NULL &&
match_branch(refname, worktree_branch))) {
err = fetch_ref(ibuf, have_refs, &have[nref],
- &want[nref], refname, id_str);
+ &want[nref], refname, id_str, algo);
if (err)
goto done;
nref++;
@@ -515,7 +523,7 @@ fetch_pack(int fd, int packfd, uint8_t *pack_sha1,
}
if (pe != NULL) {
err = fetch_ref(ibuf, have_refs, &have[nref],
- &want[nref], refname, id_str);
+ &want[nref], refname, id_str, algo);
if (err)
goto done;
nref++;
@@ -529,6 +537,9 @@ fetch_pack(int fd, int packfd, uint8_t *pack_sha1,
if (list_refs_only)
goto done;
+ got_hash_init(&ctx, algo);
+ idlen = got_hash_digest_length(algo);
+
/*
* If -b was not used and either none of the requested branches
* (got.conf, worktree) were found or the client already has the
@@ -545,7 +556,7 @@ fetch_pack(int fd, int packfd, uint8_t *pack_sha1,
if (!found_branch || remote_head_changed) {
err = fetch_ref(ibuf, have_refs, &have[nref],
- &want[nref], default_branch, default_id_str);
+ &want[nref], default_branch, default_id_str, algo);
if (err)
goto done;
nref++;
@@ -640,14 +651,12 @@ fetch_pack(int fd, int packfd, uint8_t *pack_sha1,
*/
break;
}
- if (n < 4 + SHA1_DIGEST_STRING_LENGTH ||
- strncmp(buf, "ACK ", 4) != 0) {
+ if (n < 4 + idlen || strncmp(buf, "ACK ", 4) != 0) {
err = got_error_msg(GOT_ERR_BAD_PACKET,
"unexpected message from server");
goto done;
}
- if (!got_parse_object_id(&common_id, buf + 4,
- GOT_HASH_SHA1)) {
+ if (!got_parse_object_id(&common_id, buf + 4, algo)) {
err = got_error_msg(GOT_ERR_BAD_PACKET,
"bad object ID in ACK packet from server");
goto done;
@@ -779,14 +788,15 @@ fetch_pack(int fd, int packfd, uint8_t *pack_sha1,
}
/*
- * An expected SHA1 checksum sits at the end of the pack file.
+ * An expected checksum sits at the end of the pack file.
* Since we don't know the file size ahead of time we have to
- * keep SHA1_DIGEST_LENGTH bytes buffered and avoid mixing
- * those bytes into our SHA1 checksum computation until we
- * know for sure that additional pack file data bytes follow.
+ * keep idlen bytes buffered and avoid mixing those
+ * bytes into our checksum computation until we know
+ * for sure that additional pack file data bytes
+ * follow.
*/
- if (r < SHA1_DIGEST_LENGTH) {
- if (sha1_buf_len < SHA1_DIGEST_LENGTH) {
+ if (r < idlen) {
+ if (sha1_buf_len < idlen) {
/*
* If there's enough buffered + read data to
* fill up the buffer then shift a sufficient
@@ -794,9 +804,9 @@ fetch_pack(int fd, int packfd, uint8_t *pack_sha1,
* room, mixing those bytes into the checksum.
*/
if (sha1_buf_len > 0 &&
- sha1_buf_len + r > SHA1_DIGEST_LENGTH) {
+ sha1_buf_len + r > idlen) {
size_t nshift = MIN(sha1_buf_len + r -
- SHA1_DIGEST_LENGTH, sha1_buf_len);
+ idlen, sha1_buf_len);
got_hash_update(&ctx, sha1_buf,
nshift);
memmove(sha1_buf, sha1_buf + nshift,
@@ -824,12 +834,11 @@ fetch_pack(int fd, int packfd, uint8_t *pack_sha1,
got_hash_update(&ctx, sha1_buf, sha1_buf_len);
/* Mix in bytes read minus potential checksum bytes. */
- got_hash_update(&ctx, buf, r - SHA1_DIGEST_LENGTH);
+ got_hash_update(&ctx, buf, r - idlen);
/* Buffer potential checksum bytes. */
- memcpy(sha1_buf, buf + r - SHA1_DIGEST_LENGTH,
- SHA1_DIGEST_LENGTH);
- sha1_buf_len = SHA1_DIGEST_LENGTH;
+ memcpy(sha1_buf, buf + r - idlen, idlen);
+ sha1_buf_len = idlen;
}
/* Write packfile data to temporary pack file. */
@@ -856,9 +865,11 @@ fetch_pack(int fd, int packfd, uint8_t *pack_sha1,
if (err)
goto done;
- got_hash_final(&ctx, pack_sha1);
- if (sha1_buf_len != SHA1_DIGEST_LENGTH ||
- memcmp(pack_sha1, sha1_buf, sha1_buf_len) != 0) {
+ got_hash_final_object_id(&ctx, pack_hash);
+ if (sha1_buf_len != idlen ||
+ memcmp(pack_hash, sha1_buf, sha1_buf_len) != 0) {
+ fprintf(stderr, "error'd due to a length mismatch? %d\n",
+ sha1_buf_len != idlen);
err = got_error_msg(GOT_ERR_BAD_PACKFILE,
"pack file checksum mismatch");
}
@@ -881,7 +892,7 @@ main(int argc, char **argv)
{
const struct got_error *err = NULL;
int fetchfd = -1, packfd = -1;
- uint8_t pack_sha1[SHA1_DIGEST_LENGTH];
+ struct got_object_id pack_hash;
struct imsgbuf ibuf;
struct imsg imsg;
struct got_pathlist_head have_refs;
@@ -1118,8 +1129,8 @@ main(int argc, char **argv)
}
packfd = imsg_get_fd(&imsg);
- err = fetch_pack(fetchfd, packfd, pack_sha1, &have_refs,
- fetch_req.fetch_all_branches, &wanted_branches,
+ err = fetch_pack(fetchfd, packfd, fetch_req.expected_algo, &pack_hash,
+ &have_refs, fetch_req.fetch_all_branches, &wanted_branches,
&wanted_refs, fetch_req.list_refs_only,
worktree_branch, remote_head, fetch_req.no_head, &ibuf);
done:
@@ -1134,7 +1145,7 @@ done:
if (err != NULL)
got_privsep_send_error(&ibuf, err);
else
- err = send_fetch_done(&ibuf, pack_sha1);
+ err = send_fetch_done(&ibuf, &pack_hash);
if (err != NULL) {
fprintf(stderr, "%s: %s\n", getprogname(), err->msg);
got_privsep_send_error(&ibuf, err);
blob - 2b33d0505edd3aa5545c887e21762b4336279c95
blob + 1d666b672c3967a41fcb77f441ce79cece179521
--- libexec/got-send-pack/got-send-pack.c
+++ libexec/got-send-pack/got-send-pack.c
@@ -73,6 +73,7 @@ static const struct got_capability got_capabilities[]
#endif
{ GOT_CAPA_REPORT_STATUS, NULL },
{ GOT_CAPA_DELETE_REFS, NULL },
+ { GOT_CAPA_OBJECT_FORMAT, "sha256" },
};
static const struct got_error *
@@ -341,14 +342,14 @@ describe_refchange(int *n, int *sent_my_capabilites,
}
static const struct got_error *
-send_pack(int fd, struct got_pathlist_head *refs,
+send_pack(int fd, enum got_hash_algorithm algo, struct got_pathlist_head *refs,
struct got_pathlist_head *delete_refs, struct imsgbuf *ibuf)
{
const struct got_error *err = NULL;
char buf[GOT_PKT_MAX];
- const unsigned char zero_id[SHA1_DIGEST_LENGTH] = { 0 };
- char old_hashstr[SHA1_DIGEST_STRING_LENGTH];
- char new_hashstr[SHA1_DIGEST_STRING_LENGTH];
+ const unsigned char zero_id[GOT_HASH_DIGEST_MAXLEN] = { 0 };
+ char old_hashstr[GOT_HASH_DIGEST_STRING_MAXLEN];
+ char new_hashstr[GOT_HASH_DIGEST_STRING_MAXLEN];
struct got_pathlist_head their_refs;
int is_firstpkt = 1;
int n, nsent = 0;
@@ -382,6 +383,8 @@ send_pack(int fd, struct got_pathlist_head *refs,
if (err)
goto done;
if (is_firstpkt) {
+ enum got_hash_algorithm expected_algo = algo;
+
if (server_capabilities == NULL) {
server_capabilities = strdup("");
if (server_capabilities == NULL) {
@@ -394,9 +397,13 @@ send_pack(int fd, struct got_pathlist_head *refs,
getprogname(), server_capabilities);
err = got_gitproto_match_capabilities(&my_capabilities,
NULL, server_capabilities, got_capabilities,
- nitems(got_capabilities));
+ nitems(got_capabilities), &expected_algo);
if (err)
goto done;
+ if (algo != expected_algo) {
+ err = got_error(GOT_ERR_OBJECT_FORMAT);
+ goto done;
+ }
if (chattygot)
fprintf(stderr, "%s: my capabilities:%s\n",
getprogname(),
@@ -416,7 +423,7 @@ send_pack(int fd, struct got_pathlist_head *refs,
err = got_error_from_errno("malloc");
goto done;
}
- if (!got_parse_object_id(id, id_str, GOT_HASH_SHA1)) {
+ if (!got_parse_object_id(id, id_str, algo)) {
err = got_error(GOT_ERR_BAD_OBJ_ID_STR);
goto done;
}
@@ -472,8 +479,8 @@ send_pack(int fd, struct got_pathlist_head *refs,
got_object_id_hex(their_id, old_hashstr,
sizeof(old_hashstr));
- got_sha1_digest_to_str(zero_id, new_hashstr,
- sizeof(new_hashstr));
+ got_hash_digest_to_str(zero_id, new_hashstr,
+ sizeof(new_hashstr), algo);
err = describe_refchange(&n, &sent_my_capabilites,
my_capabilities, buf, sizeof(buf), refname,
old_hashstr, new_hashstr);
@@ -515,8 +522,8 @@ send_pack(int fd, struct got_pathlist_head *refs,
got_object_id_hex(their_id, old_hashstr,
sizeof(old_hashstr));
} else {
- got_sha1_digest_to_str(zero_id, old_hashstr,
- sizeof(old_hashstr));
+ got_hash_digest_to_str(zero_id, old_hashstr,
+ sizeof(old_hashstr), algo);
}
got_object_id_hex(id, new_hashstr, sizeof(new_hashstr));
err = describe_refchange(&n, &sent_my_capabilites,
@@ -734,7 +741,7 @@ main(int argc, char **argv)
imsg_free(&imsg);
}
- err = send_pack(sendfd, &refs, &delete_refs, &ibuf);
+ err = send_pack(sendfd, send_req.algo, &refs, &delete_refs, &ibuf);
done:
got_pathlist_free(&refs, GOT_PATHLIST_FREE_ALL);
got_pathlist_free(&delete_refs, GOT_PATHLIST_FREE_ALL);
initial sha256 support in the network protocol