This is a low-level option for resumable fetch. You start a resumable fetch with git fetch --resume-pack=blah <host> where "blah" file does not exist. If the fetch is interrupted, "blah" will contain what's been fetched so far. Run the same command again. On the server side, pack-objects performs the exact same operation to produce full pack again, but it will not send what is already in "blah". pack-objects does check if the skipped part is the same between two sides, in case of configuration change or whatever, and abort early. On the client side, index-pack feeds itself with what's in "blah", then the input stream from pack-objects. index-pack does strict verification as usual. Even if pack-objects fails to produce a stable pack, index-pack should catch it and complain loudly. If everything goes well, "blah" is removed and a new good pack is put in $GIT_DIR. Improvement point. We should be able to perform some heavy operations locally before connecting to the server (e.g. produce the skip hash from "blah", or index-pack consuming "blah"). Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx> --- builtin/fetch-pack.c | 4 ++++ builtin/fetch.c | 5 +++++ remote-curl.c | 8 +++++++- transport.c | 4 ++++ transport.h | 4 ++++ 5 files changed, 24 insertions(+), 1 deletion(-) diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c index 9b2a514..996ad30 100644 --- a/builtin/fetch-pack.c +++ b/builtin/fetch-pack.c @@ -129,6 +129,10 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix) args.update_shallow = 1; continue; } + if (skip_prefix(arg, "--resume-path=", &arg)) { + args.resume_path = arg; + continue; + } usage(fetch_pack_usage); } diff --git a/builtin/fetch.c b/builtin/fetch.c index 8e74213..34f32c6 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -48,6 +48,7 @@ static const char *recurse_submodules_default; static int shown_url = 0; static int refmap_alloc, refmap_nr; static const char **refmap_array; +static const char *resume_path; static int option_parse_recurse_submodules(const struct option *opt, const char *arg, int unset) @@ -115,6 +116,8 @@ static struct option builtin_fetch_options[] = { OPT_BOOL(0, "progress", &progress, N_("force progress reporting")), OPT_STRING(0, "depth", &depth, N_("depth"), N_("deepen history of shallow clone")), + OPT_FILENAME(0, "resume-pack", &resume_path, + N_("perform resumable fetch on the given pack")), { OPTION_SET_INT, 0, "unshallow", &unshallow, NULL, N_("convert to a complete repository"), PARSE_OPT_NONEG | PARSE_OPT_NOARG, NULL, 1 }, @@ -872,6 +875,8 @@ static struct transport *prepare_transport(struct remote *remote) set_option(transport, TRANS_OPT_DEPTH, depth); if (update_shallow) set_option(transport, TRANS_OPT_UPDATE_SHALLOW, "yes"); + if (resume_path) + set_option(transport, TRANS_OPT_RESUME_PATH, resume_path); return transport; } diff --git a/remote-curl.c b/remote-curl.c index c704857..36835fb 100644 --- a/remote-curl.c +++ b/remote-curl.c @@ -20,6 +20,7 @@ static struct strbuf url = STRBUF_INIT; struct options { int verbosity; unsigned long depth; + const char *resume_path; unsigned progress : 1, check_self_contained_and_connected : 1, cloning : 1, @@ -119,6 +120,9 @@ static int set_option(const char *name, const char *value) else return -1; return 0; + } else if (!strcmp(name, "resume-path")) { + options.resume_path = xstrdup(value); + return 0; } else { return 1 /* unsupported */; } @@ -727,7 +731,7 @@ static int fetch_git(struct discovery *heads, struct strbuf preamble = STRBUF_INIT; char *depth_arg = NULL; int argc = 0, i, err; - const char *argv[17]; + const char *argv[18]; argv[argc++] = "fetch-pack"; argv[argc++] = "--stateless-rpc"; @@ -755,6 +759,8 @@ static int fetch_git(struct discovery *heads, depth_arg = strbuf_detach(&buf, NULL); argv[argc++] = depth_arg; } + if (options.resume_path) + argv[argc++] = xstrfmt("--resume-path=%s", options.resume_path); argv[argc++] = url.buf; argv[argc++] = NULL; diff --git a/transport.c b/transport.c index 67f3666..6378bed 100644 --- a/transport.c +++ b/transport.c @@ -467,6 +467,9 @@ static int set_git_option(struct git_transport_options *opts, } else if (!strcmp(name, TRANS_OPT_UPDATE_SHALLOW)) { opts->update_shallow = !!value; return 0; + } else if (!strcmp(name, TRANS_OPT_RESUME_PATH)) { + opts->resume_path = value; + return 0; } else if (!strcmp(name, TRANS_OPT_DEPTH)) { if (!value) opts->depth = 0; @@ -534,6 +537,7 @@ static int fetch_refs_via_pack(struct transport *transport, data->options.check_self_contained_and_connected; args.cloning = transport->cloning; args.update_shallow = data->options.update_shallow; + args.resume_path = data->options.resume_path; if (!data->got_remote_heads) { connect_setup(transport, 0, 0); diff --git a/transport.h b/transport.h index 8ebaaf2..765e4e5 100644 --- a/transport.h +++ b/transport.h @@ -16,6 +16,7 @@ struct git_transport_options { const char *uploadpack; const char *receivepack; struct push_cas_option *cas; + const char *resume_path; }; struct transport { @@ -180,6 +181,9 @@ int transport_restrict_protocols(void); /* Send push certificates */ #define TRANS_OPT_PUSH_CERT "pushcert" +/* Resumable fetch */ +#define TRANS_OPT_RESUME_PATH "resume-path" + /** * Returns 0 if the option was used, non-zero otherwise. Prints a * message to stderr if the option is not used. -- 2.7.0.377.g4cd97dd -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html