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 <pclo...@gmail.com>
---
 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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to