Download raw body.
initial sha256 support in the network protocol
On Sat, Feb 07, 2026 at 06:04:18PM +0100, Omar Polo wrote:
> 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.
This makes 'got clone' work for me on top of your diff.
I am running out of time for today so I cannot tidy this up right now.
I hope this allows you to make progress towards getting tests to pass.
M cvg/cvg.c | 19+ 2-
M got/got.c | 17+ 2-
M include/got_fetch.h | 5+ 2-
M include/got_repository.h | 9+ 0-
M lib/fetch.c | 28+ 19-
M lib/gitproto.c | 11+ 11-
M lib/got_lib_gitproto.h | 3+ 0-
M lib/got_lib_privsep.h | 1+ 0-
M lib/got_lib_repository.h | 1+ 0-
M lib/privsep.c | 8+ 2-
M lib/repository.c | 19+ 11-
M lib/repository_init.c | 65+ 17-
M lib/worktree_cvg.c | 2+ 0-
M libexec/got-fetch-pack/got-fetch-pack.c | 32+ 1-
14 files changed, 220 insertions(+), 67 deletions(-)
commit - 3a30796e10c8ba3088bedf613d9e911264cebfad
commit + db093745dd4861787944b61f3dca257620255914
blob - 8bc47fb2cbcc88f89ff5dc2e9eb2cf7445f26c88
blob + db25d3304e991eac1c7422383a0559ca74c1a134
--- cvg/cvg.c
+++ cvg/cvg.c
@@ -1009,6 +1009,7 @@ struct got_fetch_progress_arg {
const char *git_url;
int fetch_all_branches;
int mirror_references;
+ int expected_algo;
} config_info;
};
@@ -1022,6 +1023,7 @@ create_config_files(const char *proto, const char *hos
static const struct got_error *
fetch_progress(void *arg, const char *message, off_t packfile_size,
+ struct got_object_id *pack_hash,
int nobj_total, int nobj_indexed, int nobj_loose, int nobj_resolved)
{
const struct got_error *err = NULL;
@@ -1038,6 +1040,14 @@ fetch_progress(void *arg, const char *message, off_t p
*/
if (a->create_configs && !a->configs_created &&
!RB_EMPTY(a->config_info.symrefs)) {
+ if (a->config_info.expected_algo == -1 &&
+ pack_hash->algo == GOT_HASH_SHA256) {
+ err = got_repo_init_gitconfig(a->repo,
+ pack_hash->algo);
+ if (err)
+ return err;
+ }
+
err = create_config_files(a->config_info.proto,
a->config_info.host, a->config_info.port,
a->config_info.remote_repo_path,
@@ -1049,6 +1059,7 @@ fetch_progress(void *arg, const char *message, off_t p
a->config_info.wanted_refs, a->repo);
if (err)
return err;
+
a->configs_created = 1;
}
@@ -1721,10 +1732,11 @@ cmd_clone(int argc, char *argv[])
fpa.config_info.git_url = git_url;
fpa.config_info.fetch_all_branches = fetch_all_branches;
fpa.config_info.mirror_references = mirror_references;
+ fpa.config_info.expected_algo = -1;
error = got_fetch_pack(&pack_hash, &refs, &symrefs,
GOT_FETCH_DEFAULT_REMOTE_NAME, mirror_references,
fetch_all_branches, &wanted_branches, &wanted_refs,
- list_refs_only, verbosity, fetchfd, repo, NULL, NULL, bflag,
+ list_refs_only, verbosity, -1, fetchfd, repo, NULL, NULL, bflag,
fetch_progress, &fpa);
if (error)
goto done;
@@ -2678,6 +2690,7 @@ cmd_update(int argc, char *argv[])
int delete_remote = 0;
int replace_tags = 0;
int *pack_fds = NULL;
+ int expected_algo;
const char *remote_head = NULL, *worktree_branch = NULL;
struct got_object_id *commit_id = NULL;
char *commit_id_str = NULL;
@@ -2902,6 +2915,8 @@ cmd_update(int argc, char *argv[])
if (strncmp(refname, "refs/heads/", 11) == 0)
worktree_branch = refname;
+ expected_algo = got_repo_get_object_format(repo);
+
fpa.last_scaled_size[0] = '\0';
fpa.last_p_indexed = -1;
fpa.last_p_resolved = -1;
@@ -2910,10 +2925,12 @@ cmd_update(int argc, char *argv[])
fpa.create_configs = 0;
fpa.configs_created = 0;
memset(&fpa.config_info, 0, sizeof(fpa.config_info));
+ fpa.config_info.expected_algo = expected_algo;
error = got_fetch_pack(&pack_hash, &refs, &symrefs, remote->name,
remote->mirror_references, 0, &wanted_branches, &wanted_refs,
- 0, verbosity, fetchfd, repo, worktree_branch, remote_head,
+ 0, verbosity, expected_algo,
+ fetchfd, repo, worktree_branch, remote_head,
0, fetch_progress, &fpa);
if (error)
goto done;
blob - 487b4865e729be9a32fd1157ab96adf4e609986e
blob + a53709f8fc2cca37ac4090e5a082fdad48899dcf
--- got/got.c
+++ got/got.c
@@ -1098,6 +1098,7 @@ struct got_fetch_progress_arg {
const char *git_url;
int fetch_all_branches;
int mirror_references;
+ int expected_algo;
} config_info;
};
@@ -1111,6 +1112,7 @@ create_config_files(const char *proto, const char *hos
static const struct got_error *
fetch_progress(void *arg, const char *message, off_t packfile_size,
+ struct got_object_id *pack_hash,
int nobj_total, int nobj_indexed, int nobj_loose, int nobj_resolved)
{
const struct got_error *err = NULL;
@@ -1127,6 +1129,14 @@ fetch_progress(void *arg, const char *message, off_t p
*/
if (a->create_configs && !a->configs_created &&
!RB_EMPTY(a->config_info.symrefs)) {
+ if (a->config_info.expected_algo == -1 &&
+ pack_hash->algo == GOT_HASH_SHA256) {
+ err = got_repo_init_gitconfig(a->repo,
+ pack_hash->algo);
+ if (err)
+ return err;
+ }
+
err = create_config_files(a->config_info.proto,
a->config_info.host, a->config_info.port,
a->config_info.remote_repo_path,
@@ -1138,6 +1148,7 @@ fetch_progress(void *arg, const char *message, off_t p
a->config_info.wanted_refs, a->repo);
if (err)
return err;
+
a->configs_created = 1;
}
@@ -1820,10 +1831,11 @@ cmd_clone(int argc, char *argv[])
fpa.config_info.git_url = git_url;
fpa.config_info.fetch_all_branches = fetch_all_branches;
fpa.config_info.mirror_references = mirror_references;
+ fpa.config_info.expected_algo = -1;
error = got_fetch_pack(&pack_hash, &refs, &symrefs,
GOT_FETCH_DEFAULT_REMOTE_NAME, mirror_references,
fetch_all_branches, &wanted_branches, &wanted_refs,
- list_refs_only, verbosity, fetchfd, repo, NULL, NULL, bflag,
+ list_refs_only, verbosity, -1, fetchfd, repo, NULL, NULL, bflag,
fetch_progress, &fpa);
if (error)
goto done;
@@ -2762,11 +2774,14 @@ cmd_fetch(int argc, char *argv[])
fpa.repo = repo;
fpa.create_configs = 0;
fpa.configs_created = 0;
+ fpa.config_info.expected_algo = got_repo_get_object_format(repo);
memset(&fpa.config_info, 0, sizeof(fpa.config_info));
+
error = got_fetch_pack(&pack_hash, &refs, &symrefs, remote->name,
remote->mirror_references, fetch_all_branches, &wanted_branches,
- &wanted_refs, list_refs_only, verbosity, fetchfd, repo,
+ &wanted_refs, list_refs_only, verbosity,
+ got_repo_get_object_format(repo), fetchfd, repo,
worktree_branch, remote_head, have_bflag, fetch_progress, &fpa);
if (error)
goto done;
blob - 4e7f538f523c582bd0b2b8be1e97182731a9ec7e
blob + 514769c17e48227a0ef18ab5759fca1cde588c37
--- include/got_fetch.h
+++ include/got_fetch.h
@@ -37,16 +37,19 @@ const struct got_error *got_fetch_connect(pid_t *, int
/* A callback function which gets invoked with progress information to print. */
typedef const struct got_error *(*got_fetch_progress_cb)(void *,
- const char *, off_t, int, int, int, int);
+ const char *, off_t, struct got_object_id *, int, int, int, int);
/*
* Attempt to fetch a packfile from a server. This pack file will contain
* objects which that are not yet contained in the provided repository.
* Return the hash of the packfile (in form of an object ID) and lists of
* references and symbolic references learned from the server.
+ * The expected object ID format is either from got_repo_get_object_format(),
+ * or can be passed as -1 to discover the server's object iD hash format
+ * when cloning a fresh repository.
*/
const struct got_error *got_fetch_pack(struct got_object_id **,
struct got_pathlist_head *, struct got_pathlist_head *, const char *,
int, int, struct got_pathlist_head *, struct got_pathlist_head *,
- int, int, int, struct got_repository *, const char *, const char *,
+ int, int, int, int, struct got_repository *, const char *, const char *,
int, got_fetch_progress_cb, void *);
blob - 89dabf01804eecca3d8273fcc04ca27c031c0f5e
blob + 7703401a56a83065fab1b59a58a52079860f8bff
--- include/got_repository.h
+++ include/got_repository.h
@@ -158,6 +158,15 @@ const struct got_error *got_repo_map_path(char **, str
const struct got_error *got_repo_init(const char *, const char *,
enum got_hash_algorithm);
+/*
+ * Create a new config file for git in the specified repository,
+ * resetting parameters such as the object Id hash algorithm.
+ * Should only be used if the repository is freshly cloned and has
+ * wrong setings in the existing configuration file.
+ */
+const struct got_error *got_repo_init_gitconfig(struct got_repository *,
+ enum got_hash_algorithm);
+
/* Attempt to find a unique object ID for a given ID string prefix. */
const struct got_error *got_repo_match_object_id_prefix(struct got_object_id **,
const char *, int, struct got_repository *);
blob - b78727982872932c8a61d31ef72455d7c93c4b63
blob + ef20ad90080e0a5bfb77b37b0d2dd3144a0d28c5
--- lib/fetch.c
+++ lib/fetch.c
@@ -111,7 +111,8 @@ got_fetch_pack(struct got_object_id **pack_hash, struc
int mirror_references, int fetch_all_branches,
struct got_pathlist_head *wanted_branches,
struct got_pathlist_head *wanted_refs, int list_refs_only, int verbosity,
- int fetchfd, struct got_repository *repo, const char *worktree_refname,
+ int expected_algo, int fetchfd, struct got_repository *repo,
+ const char *worktree_refname,
const char *remote_head, int no_head, got_fetch_progress_cb progress_cb,
void *progress_arg)
{
@@ -135,8 +136,7 @@ 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;
+ size_t idlen = 0;
*pack_hash = NULL;
memset(&fetchibuf, 0, sizeof(fetchibuf));
@@ -155,13 +155,7 @@ 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++)
@@ -285,8 +279,8 @@ 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, algo, &have_refs,
- fetch_all_branches, wanted_branches, wanted_refs,
+ err = got_privsep_send_fetch_req(&fetchibuf, nfetchfd, expected_algo,
+ &have_refs, fetch_all_branches, wanted_branches, wanted_refs,
list_refs_only, worktree_refname, remote_head, no_head, verbosity);
if (err != NULL)
goto done;
@@ -325,6 +319,26 @@ got_fetch_pack(struct got_object_id **pack_hash, struc
&packfile_size_cur, *pack_hash, &fetchibuf);
if (err != NULL)
goto done;
+
+ /* Hash algorithm must now be known. */
+ switch ((*pack_hash)->algo) {
+ case GOT_HASH_SHA1:
+ case GOT_HASH_SHA256:
+ idlen = got_hash_digest_length((*pack_hash)->algo);
+ break;
+ default:
+ err = got_error_fmt(GOT_ERR_OBJECT_FORMAT,
+ "could not determine object hash algorithm "
+ "used by server");
+ goto done;
+ }
+
+ if (expected_algo != -1 &&
+ (*pack_hash)->algo != expected_algo) {
+ err = got_error(GOT_ERR_OBJECT_FORMAT);
+ goto done;
+ }
+
/* Don't report size progress for an empty pack file. */
if (packfile_size_cur <= ssizeof(pack_hdr) + idlen)
packfile_size_cur = 0;
@@ -361,7 +375,7 @@ got_fetch_pack(struct got_object_id **pack_hash, struc
goto done;
}
err = progress_cb(progress_arg, s,
- packfile_size_cur, 0, 0, 0, 0);
+ packfile_size_cur, *pack_hash, 0, 0, 0, 0);
free(s);
if (err)
break;
@@ -377,7 +391,7 @@ got_fetch_pack(struct got_object_id **pack_hash, struc
goto done;
} else if (!done && packfile_size_cur != packfile_size) {
err = progress_cb(progress_arg, NULL,
- packfile_size_cur, 0, 0, 0, 0);
+ packfile_size_cur, *pack_hash, 0, 0, 0, 0);
if (err)
break;
packfile_size = packfile_size_cur;
@@ -397,11 +411,6 @@ 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);
@@ -513,7 +522,7 @@ got_fetch_pack(struct got_object_id **pack_hash, struc
goto done;
if (nobj_indexed != 0) {
err = progress_cb(progress_arg, NULL,
- packfile_size, nobj_total,
+ packfile_size, *pack_hash, nobj_total,
nobj_indexed, nobj_loose, nobj_resolved);
if (err)
break;
blob - f63af5151c343acd415e881e2ef503a4471825b0
blob + 7fae1f6aa9fecd6d20e4425f3c5e98240cc8e904
--- lib/gitproto.c
+++ lib/gitproto.c
@@ -232,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, enum got_hash_algorithm *algo)
+ const struct got_capability *mycapa)
{
char *equalsign;
char *s;
@@ -241,15 +241,6 @@ 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;
@@ -331,9 +322,18 @@ got_gitproto_match_capabilities(char **common_capabili
continue;
}
+ if (equalsign != NULL &&
+ strncmp(capa, GOT_CAPA_OBJECT_FORMAT,
+ equalsign - capa) == 0) {
+ if (strcmp(equalsign + 1,
+ GOT_CAPA_OBJECT_FORMAT_SHA256) == 0)
+ *algo = GOT_HASH_SHA256;
+ continue;
+ }
+
for (i = 0; i < ncapa; i++) {
err = match_capability(common_capabilities,
- capa, &my_capabilities[i], algo);
+ capa, &my_capabilities[i]);
if (err)
break;
}
blob - 6128c320387d0fc02ee3b1edf54f6d59de13bb86
blob + a1521e5e216928e5fa0a439146c9a9aed8187231
--- lib/got_lib_gitproto.h
+++ lib/got_lib_gitproto.h
@@ -23,6 +23,9 @@
#define GOT_CAPA_NO_THIN "no-thin"
#define GOT_CAPA_OBJECT_FORMAT "object-format"
+#define GOT_CAPA_OBJECT_FORMAT_SHA1 "sha1"
+#define GOT_CAPA_OBJECT_FORMAT_SHA256 "sha256"
+
#define GOT_SIDEBAND_PACKFILE_DATA 1
#define GOT_SIDEBAND_PROGRESS_INFO 2
#define GOT_SIDEBAND_ERROR_INFO 3
blob - 6d1e35b9cd6137e782e25a9f4f3a66450cb77a7e
blob + 7af185dfaa8a64ffa50fb31b054197de566cdc2c
--- lib/got_lib_privsep.h
+++ lib/got_lib_privsep.h
@@ -120,6 +120,7 @@ enum got_imsg_type {
GOT_IMSG_FETCH_SYMREFS,
GOT_IMSG_FETCH_REF,
GOT_IMSG_FETCH_SERVER_PROGRESS,
+ GOT_IMSG_FETCH_OBJECT_FORMAT,
GOT_IMSG_FETCH_DOWNLOAD_PROGRESS,
GOT_IMSG_FETCH_DONE,
GOT_IMSG_IDXPACK_REQUEST,
blob - 825c284a4e4d1d2d2a5c1a4d62d6ba968820390a
blob + acd75ae28f46fb7fc4e959f7e6e146cb84cadfde
--- lib/got_lib_repository.h
+++ lib/got_lib_repository.h
@@ -187,3 +187,4 @@ void got_repo_temp_fds_put(int, struct got_repository
const struct got_error *got_repo_find_object_id(struct got_object_id *,
struct got_repository *);
+void got_repo_free_gitconfig(struct got_repository *);
blob - 8f1d693232a9d8b268ee215889b827c3ea255cce
blob + 4a1a7a694b548d7263ffc7c0a9a288c158de4ff5
--- lib/privsep.c
+++ lib/privsep.c
@@ -714,7 +714,8 @@ 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, struct got_object_id *pack_hash, 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;
@@ -730,7 +731,6 @@ got_privsep_recv_fetch_progress(int *done, struct got_
*refname = NULL;
*server_progress = NULL;
*packfile_size = 0;
- memset(pack_hash, 0, sizeof(*pack_hash));
err = got_privsep_recv_imsg(&imsg, ibuf, 0);
if (err)
@@ -838,6 +838,12 @@ got_privsep_recv_fetch_progress(int *done, struct got_
}
memcpy(packfile_size, imsg.data, sizeof(*packfile_size));
break;
+ case GOT_IMSG_FETCH_OBJECT_FORMAT:
+ if (imsg_get_data(&imsg, pack_hash, sizeof(*pack_hash)) == -1) {
+ err = got_error(GOT_ERR_PRIVSEP_MSG);
+ break;
+ }
+ break;
case GOT_IMSG_FETCH_DONE:
if (imsg_get_data(&imsg, pack_hash, sizeof(*pack_hash)) == -1) {
err = got_error(GOT_ERR_PRIVSEP_MSG);
blob - 14731673ee55811e65071b506239d1af5c93077a
blob + 5d954c5b18dc87b456b4f3fb1e85a55226c82c41
--- lib/repository.c
+++ lib/repository.c
@@ -844,6 +844,24 @@ done:
return err;
}
+void
+got_repo_free_gitconfig(struct got_repository *repo)
+{
+ size_t i;
+
+ free(repo->gitconfig_author_name);
+ free(repo->gitconfig_author_email);
+ for (i = 0; i < repo->ngitconfig_remotes; i++)
+ got_repo_free_remote_repo_data(&repo->gitconfig_remotes[i]);
+ free(repo->gitconfig_remotes);
+ for (i = 0; i < repo->nextensions; i++) {
+ free(repo->extnames[i]);
+ free(repo->extvals[i]);
+ }
+ free(repo->extnames);
+ free(repo->extvals);
+}
+
const struct got_error *
got_repo_close(struct got_repository *repo)
{
@@ -903,17 +921,7 @@ got_repo_close(struct got_repository *repo)
if (repo->gotconfig)
got_gotconfig_free(repo->gotconfig);
- free(repo->gitconfig_author_name);
- free(repo->gitconfig_author_email);
- for (i = 0; i < repo->ngitconfig_remotes; i++)
- got_repo_free_remote_repo_data(&repo->gitconfig_remotes[i]);
- free(repo->gitconfig_remotes);
- for (i = 0; i < repo->nextensions; i++) {
- free(repo->extnames[i]);
- free(repo->extvals[i]);
- }
- free(repo->extnames);
- free(repo->extvals);
+ got_repo_free_gitconfig(repo);
got_pathlist_free(&repo->packidx_paths, GOT_PATHLIST_FREE_PATH);
free(repo);
blob - 226d9754daca5178d153ef58e08e9cb96d5b157a
blob + 398f19626c435567029d24b7cee6ce595fe25920
--- lib/repository_init.c
+++ lib/repository_init.c
@@ -25,6 +25,7 @@
#include <stdlib.h>
#include <sha1.h>
#include <sha2.h>
+#include <unistd.h>
#include "got_error.h"
#include "got_path.h"
@@ -42,6 +43,28 @@
#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
#endif
+static const struct got_error *
+init_gitconfig(const char *gitconfig_path, enum got_hash_algorithm algo)
+{
+ const char *gitconfig_sha1 = "[core]\n"
+ "\trepositoryformatversion = 0\n"
+ "\tfilemode = true\n"
+ "\tbare = true\n";
+ const char *gitconfig_sha256 = "[core]\n"
+ "\trepositoryformatversion = 1\n"
+ "\tfilemode = true\n"
+ "\tbare = true\n"
+ "[extensions]\n"
+ "\tobjectformat = sha256\n";
+ const char *gitconfig = gitconfig_sha1;
+
+ if (algo == GOT_HASH_SHA256)
+ gitconfig = gitconfig_sha256;
+
+ return got_path_create_file(gitconfig_path, gitconfig);
+}
+
+
const struct got_error *
got_repo_init(const char *repo_path, const char *head_name,
enum got_hash_algorithm algo)
@@ -55,23 +78,9 @@ got_repo_init(const char *repo_path, const char *head_
const char *description_str = "Unnamed repository; "
"edit this file 'description' to name the repository.";
const char *headref = "ref: refs/heads/";
- const char *gitconfig_sha1 = "[core]\n"
- "\trepositoryformatversion = 0\n"
- "\tfilemode = true\n"
- "\tbare = true\n";
- const char *gitconfig_sha256 = "[core]\n"
- "\trepositoryformatversion = 1\n"
- "\tfilemode = true\n"
- "\tbare = true\n"
- "[extensions]\n"
- "\tobjectformat = sha256\n";
- const char *gitconfig = gitconfig_sha1;
char *headref_str, *path;
size_t i;
- if (algo == GOT_HASH_SHA256)
- gitconfig = gitconfig_sha256;
-
if (!got_path_dir_is_empty(repo_path))
return got_error(GOT_ERR_DIR_NOT_EMPTY);
@@ -107,10 +116,49 @@ got_repo_init(const char *repo_path, const char *head_
if (asprintf(&path, "%s/%s", repo_path, "config") == -1)
return got_error_from_errno("asprintf");
- err = got_path_create_file(path, gitconfig);
+
+ err = init_gitconfig(path, algo);
free(path);
+ return err;
+}
+
+const struct got_error *
+got_repo_init_gitconfig(struct got_repository *repo,
+ enum got_hash_algorithm algo)
+{
+ const struct got_error *err;
+ char *path;
+
+ path = got_repo_get_path_gitconfig(repo);
+ if (path == NULL)
+ return got_error_from_errno("got_repo_get_path_gitconfig");
+
+ if (unlink(path) == -1) {
+ err = got_error_from_errno2("unlink", path);
+ goto done;
+ }
+
+ err = init_gitconfig(path, algo);
if (err)
- return err;
+ goto done;
+
+ got_repo_free_gitconfig(repo);
- return NULL;
+ repo->algo = algo;
+
+ if (getenv("GOT_IGNORE_GITCONFIG") != NULL) {
+ err = got_repo_read_gitconfig(
+ &repo->gitconfig_repository_format_version,
+ &repo->gitconfig_author_name, &repo->gitconfig_author_email,
+ &repo->gitconfig_remotes, &repo->ngitconfig_remotes,
+ &repo->gitconfig_owner, &repo->extnames, &repo->extvals,
+ &repo->nextensions, path);
+ if (err)
+ goto done;
+ } else if (algo == GOT_HASH_SHA256)
+ repo->gitconfig_repository_format_version = 1;
+done:
+ free(path);
+ return err;
+
}
blob - 5b9b1c532c0d687ea6a7630ba195c953fd2add73
blob + 04ac785139414457c03c21d8bbedf5c7df84c027
--- lib/worktree_cvg.c
+++ lib/worktree_cvg.c
@@ -2596,6 +2596,7 @@ struct got_fetch_progress_arg {
static const struct got_error *
fetch_progress(void *arg, const char *message, off_t packfile_size,
+ struct got_object_id *pack_hash,
int nobj_total, int nobj_indexed, int nobj_loose, int nobj_resolved)
{
struct got_fetch_progress_arg *a = arg;
@@ -2805,6 +2806,7 @@ fetch_updated_remote(const char *proto, const char *ho
err = got_fetch_pack(&pack_hash, &learned_refs, &symrefs,
remote->name, 1, 0, &wanted_branches, &wanted_refs, 0, verbosity,
+ got_repo_get_object_format(repo),
fetchfd, repo, head_refname, NULL, 0, fetch_progress, &fpa);
if (err)
goto done;
blob - ef7f20aedafd9c0d532e4b464943c35f2f88b582
blob + cb16d011377640803090d492c6e35ff56a102a15
--- libexec/got-fetch-pack/got-fetch-pack.c
+++ libexec/got-fetch-pack/got-fetch-pack.c
@@ -274,6 +274,15 @@ send_fetch_symrefs(struct imsgbuf *ibuf, struct got_pa
}
static const struct got_error *
+send_object_format(struct imsgbuf *ibuf, struct got_object_id *pack_hash)
+{
+ if (imsg_compose(ibuf, GOT_IMSG_FETCH_OBJECT_FORMAT, 0, 0, -1,
+ pack_hash, sizeof(*pack_hash)) == -1)
+ return got_error_from_errno("imsg_compose FETCH_OBJECT_FORMAT");
+ return got_privsep_flush_imsg(ibuf);
+}
+
+static const struct got_error *
send_fetch_ref(struct imsgbuf *ibuf, struct got_object_id *refid,
const char *refname)
{
@@ -420,13 +429,29 @@ fetch_pack(int fd, int packfd, int expected_algo,
getprogname(), server_capabilities);
err = got_gitproto_match_capabilities(&my_capabilities,
&symrefs, server_capabilities,
- got_capabilities, nitems(got_capabilities), &algo);
+ 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 (algo == GOT_HASH_SHA256) {
+ char *s;
+
+ if (asprintf(&s, "%s%s%s=%s", my_capabilities,
+ my_capabilities[0] != '\0' ? " " : "",
+ GOT_CAPA_OBJECT_FORMAT,
+ GOT_CAPA_OBJECT_FORMAT_SHA256) == -1) {
+ err = got_error_from_errno("asprintf");
+ goto done;
+ }
+ free(my_capabilities);
+ my_capabilities = s;
+ }
+
if (chattygot)
fprintf(stderr, "%s: my capabilities:%s\n",
getprogname(), my_capabilities != NULL ?
@@ -434,6 +459,12 @@ fetch_pack(int fd, int packfd, int expected_algo,
err = send_fetch_symrefs(ibuf, &symrefs);
if (err)
goto done;
+
+ pack_hash->algo = algo;
+ err = send_object_format(ibuf, pack_hash);
+ if (err)
+ goto done;
+
is_firstpkt = 0;
if (!fetch_all_branches) {
RB_FOREACH(pe, got_pathlist_head, &symrefs) {
initial sha256 support in the network protocol