commit - 5f3e316cffd649c7f4164a0c825f4847082a2875
commit + a5a5a156a91a17c59934179af8eca099a95b6c2d
blob - 8b52a98aa8b52fe2d3775b7f19516cb967ebdec3
blob + cc02089bfcb70faf1775da8b8a38eb7bfd903018
--- include/got_error.h
+++ include/got_error.h
#define GOT_ERR_MERGE_COMMIT_OUT_OF_DATE 170
#define GOT_ERR_BUNDLE_FORMAT 171
#define GOT_ERR_BAD_KEYWORD 172
+#define GOT_ERR_UNKNOWN_CAPA 173
struct got_error {
int code;
blob - 2897f7222b41cd87986de117e09ca594c4bef16f
blob + 8872bef06f42c654a7f90d728cc11aadb624cf2e
--- lib/error.c
+++ lib/error.c
"the work tree is no longer up-to-date; merge must be aborted "
"and retried" },
{ GOT_ERR_BUNDLE_FORMAT, "unknown git bundle version" },
- { GOT_ERR_BAD_KEYWORD, "invalid commit keyword" }
+ { GOT_ERR_BAD_KEYWORD, "invalid commit keyword" },
+ { GOT_ERR_UNKNOWN_CAPA, "unknown capability" },
};
static struct got_custom_error {
blob - 410b0e9b2cbce22df12461bda7f7e9b4cdff10aa
blob + cbb7371e15508f1be9b366e0a087a88cf080a64a
--- lib/load.c
+++ lib/load.c
#include "got_lib_privsep.h"
#define GIT_BUNDLE_SIGNATURE_V2 "# v2 git bundle\n"
+#define GIT_BUNDLE_SIGNATURE_V3 "# v3 git bundle\n"
#ifndef nitems
#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
int imsg_idxfds[2] = {-1, -1};
int ch, done, nobj, idxstatus;
pid_t idxpid;
- enum got_hash_algorithm algo;
+ enum got_hash_algorithm repo_algo, bundle_algo;
got_ratelimit_init(&rl, 0, 500);
- algo = got_repo_get_object_format(repo);
- digest_len = got_hash_digest_length(algo);
+ repo_algo = got_repo_get_object_format(repo);
+ digest_len = got_hash_digest_length(repo_algo);
repo_path = got_repo_get_path_git_dir(repo);
+ /* bundles will use v3 and a capability to advertise sha256 */
+ bundle_algo = GOT_HASH_SHA1;
+
linelen = getline(&line, &linesize, in);
if (linelen == -1) {
err = got_ferror(in, GOT_ERR_IO);
goto done;
}
- if (strcmp(line, GIT_BUNDLE_SIGNATURE_V2) != 0) {
+ if (strcmp(line, GIT_BUNDLE_SIGNATURE_V2) != 0 &&
+ strcmp(line, GIT_BUNDLE_SIGNATURE_V3) != 0) {
err = got_error(GOT_ERR_BUNDLE_FORMAT);
+ goto done;
+ }
+
+ /* Parse the capabilities */
+ for (;;) {
+ char *key, *val;
+
+ ch = fgetc(in);
+ if (ch != '@') {
+ if (ch != EOF)
+ ungetc(ch, in);
+ break;
+ }
+
+ linelen = getline(&line, &linesize, in);
+ if (linelen == -1) {
+ err = got_ferror(in, GOT_ERR_IO);
+ goto done;
+ }
+
+ if (line[linelen - 1] == '\n')
+ line[linelen - 1] = '\0';
+
+ key = line;
+ val = strchr(key, '=');
+ if (val == NULL) {
+ err = got_error_path(key, GOT_ERR_UNKNOWN_CAPA);
+ goto done;
+ }
+ *val++ = '\0';
+ if (!strcmp(key, "object-format")) {
+ if (!strcmp(val, "sha1")) {
+ bundle_algo = GOT_HASH_SHA1;
+ continue;
+ }
+ if (!strcmp(val, "sha256")) {
+ bundle_algo = GOT_HASH_SHA256;
+ continue;
+ }
+ }
+ err = got_error_path(key, GOT_ERR_UNKNOWN_CAPA);
goto done;
}
+ if (bundle_algo != repo_algo) {
+ fprintf(stderr, "%d vs %d\n", bundle_algo, repo_algo);
+ err = got_error(GOT_ERR_OBJECT_FORMAT);
+ goto done;
+ }
+
/* Parse the prerequisite */
for (;;) {
ch = fgetc(in);
if (line[linelen - 1] == '\n')
line[linelen - 1] = '\0';
- if (!got_parse_object_id(&id, line, algo)) {
+ if (!got_parse_object_id(&id, line, repo_algo)) {
err = got_error_path(line, GOT_ERR_BAD_OBJ_ID_STR);
goto done;
}
goto done;
}
- if (!got_parse_object_id(id, line, algo)) {
+ if (!got_parse_object_id(id, line, repo_algo)) {
free(id);
err = got_error(GOT_ERR_BAD_OBJ_ID_STR);
goto done;
if (err)
goto done;
- err = copypack(in, packfd, &packsiz, &id, algo, &rl,
+ err = copypack(in, packfd, &packsiz, &id, repo_algo, &rl,
progress_cb, progress_arg, cancel_cb, cancel_arg);
if (err)
goto done;