@@ -317,3 +317,8 @@ endif::git-pull[]
-6::
--ipv6::
Use IPv6 addresses only, ignoring IPv4 addresses.
+
+--bundle-uri=<uri>::
+ Instead of fetching from a remote, fetch a bundle from the given
+ `<uri>` and unbundle the data into the local repository. The refs
+ in the bundle will be stored under the `refs/bundle/*` namespace.
@@ -13,6 +13,7 @@ SYNOPSIS
'git fetch' [<options>] <group>
'git fetch' --multiple [<options>] [(<repository> | <group>)...]
'git fetch' --all [<options>]
+'git fetch' --bundle-uri=<uri> [<options>]
DESCRIPTION
@@ -29,6 +29,7 @@
#include "commit-graph.h"
#include "shallow.h"
#include "worktree.h"
+#include "bundle-uri.h"
#define FORCED_UPDATES_DELAY_WARNING_IN_MS (10 * 1000)
@@ -37,6 +38,7 @@ static const char * const builtin_fetch_usage[] = {
N_("git fetch [<options>] <group>"),
N_("git fetch --multiple [<options>] [(<repository> | <group>)...]"),
N_("git fetch --all [<options>]"),
+ N_("git fetch --bundle-uri=<uri> [<options>]"),
NULL
};
@@ -86,6 +88,7 @@ static struct string_list negotiation_tip = STRING_LIST_INIT_NODUP;
static int fetch_write_commit_graph = -1;
static int stdin_refspecs = 0;
static int negotiate_only;
+static const char *bundle_uri;
static int git_fetch_config(const char *k, const char *v, void *cb)
{
@@ -224,6 +227,8 @@ static struct option builtin_fetch_options[] = {
N_("write the commit-graph after fetching")),
OPT_BOOL(0, "stdin", &stdin_refspecs,
N_("accept refspecs from stdin")),
+ OPT_STRING(0, "bundle-uri", &bundle_uri, N_("uri"),
+ N_("download bundle data from the given URI instead of from a remote")),
OPT_END()
};
@@ -2181,6 +2186,11 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
if (dry_run)
write_fetch_head = 0;
+ if (bundle_uri) {
+ result = fetch_bundle_uri(the_repository, bundle_uri);
+ goto cleanup;
+ }
+
if (all) {
if (argc == 1)
die(_("fetch --all does not take a repository argument"));
@@ -76,11 +76,15 @@ int fetch_bundle_uri(struct repository *r, const char *uri)
struct strbuf filename = STRBUF_INIT;
find_temp_filename(&filename);
- if ((result = copy_uri_to_file(uri, filename.buf)))
+ if ((result = copy_uri_to_file(uri, filename.buf))) {
+ error(_("failed to download bundle from URI '%s'"), uri);
goto cleanup;
+ }
- if ((result = !is_bundle(filename.buf, 0)))
+ if ((result = !is_bundle(filename.buf, 0))) {
+ error(_("file at URI '%s' is not a bundle"), uri);
goto cleanup;
+ }
if ((result = unbundle_from_file(r, filename.buf)))
goto cleanup;
new file mode 100755
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+test_description='test fetching bundles with --bundle-uri'
+
+. ./test-lib.sh
+
+test_expect_success 'fail to fetch from non-existent file' '
+ test_must_fail git fetch --bundle-uri="$(pwd)/does-not-exist" 2>err &&
+ grep "failed to download bundle from URI" err
+'
+
+test_expect_success 'fail to fetch from non-bundle file' '
+ echo bogus >bogus &&
+ test_must_fail git fetch --bundle-uri="$(pwd)/bogus" 2>err &&
+ grep "is not a bundle" err
+'
+
+test_expect_success 'create bundle' '
+ git init fetch-from &&
+ git -C fetch-from checkout -b topic &&
+ test_commit -C fetch-from A &&
+ test_commit -C fetch-from B &&
+ git -C fetch-from bundle create B.bundle topic
+'
+
+test_expect_success 'fetch file bundle' '
+ git init fetch-to &&
+ git -C fetch-to fetch --bundle-uri="$(pwd)/fetch-from/B.bundle" &&
+ git -C fetch-to rev-parse refs/bundles/topic >actual &&
+ git -C fetch-from rev-parse topic >expect &&
+ test_cmp expect actual
+'
+
+test_done