summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--builtin/rev-list.c6
-rw-r--r--list-objects-filter-options.c14
-rw-r--r--list-objects-filter-options.h2
-rw-r--r--list-objects-filter.c14
-rwxr-xr-xt/t5616-partial-clone.sh36
5 files changed, 50 insertions, 22 deletions
diff --git a/builtin/rev-list.c b/builtin/rev-list.c
index b8dc2e1fba..74dbfad73d 100644
--- a/builtin/rev-list.c
+++ b/builtin/rev-list.c
@@ -471,12 +471,6 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
parse_list_objects_filter(&filter_options, arg);
if (filter_options.choice && !revs.blob_objects)
die(_("object filtering requires --objects"));
- if (filter_options.choice == LOFC_SPARSE_OID &&
- !filter_options.sparse_oid_value)
- die(
- _("invalid sparse value '%s'"),
- list_objects_filter_spec(
- &filter_options));
continue;
}
if (!strcmp(arg, ("--no-" CL_ARG__FILTER))) {
diff --git a/list-objects-filter-options.c b/list-objects-filter-options.c
index 4d88bfe64a..256bcfbdfe 100644
--- a/list-objects-filter-options.c
+++ b/list-objects-filter-options.c
@@ -62,17 +62,7 @@ static int gently_parse_list_objects_filter(
return 0;
} else if (skip_prefix(arg, "sparse:oid=", &v0)) {
- struct object_context oc;
- struct object_id sparse_oid;
-
- /*
- * Try to parse <oid-expression> into an OID for the current
- * command, but DO NOT complain if we don't have the blob or
- * ref locally.
- */
- if (!get_oid_with_context(the_repository, v0, GET_OID_BLOB,
- &sparse_oid, &oc))
- filter_options->sparse_oid_value = oiddup(&sparse_oid);
+ filter_options->sparse_oid_name = xstrdup(v0);
filter_options->choice = LOFC_SPARSE_OID;
return 0;
@@ -320,7 +310,7 @@ void list_objects_filter_release(
if (!filter_options)
return;
string_list_clear(&filter_options->filter_spec, /*free_util=*/0);
- free(filter_options->sparse_oid_value);
+ free(filter_options->sparse_oid_name);
for (sub = 0; sub < filter_options->sub_nr; sub++)
list_objects_filter_release(&filter_options->sub[sub]);
free(filter_options->sub);
diff --git a/list-objects-filter-options.h b/list-objects-filter-options.h
index b63c5ee1a3..2ffb39222c 100644
--- a/list-objects-filter-options.h
+++ b/list-objects-filter-options.h
@@ -45,7 +45,7 @@ struct list_objects_filter_options {
* some values will be defined for any given choice.
*/
- struct object_id *sparse_oid_value;
+ char *sparse_oid_name;
unsigned long blob_limit_value;
unsigned long tree_exclude_depth;
diff --git a/list-objects-filter.c b/list-objects-filter.c
index d624f1c898..1e8d4e763d 100644
--- a/list-objects-filter.c
+++ b/list-objects-filter.c
@@ -483,9 +483,17 @@ static void filter_sparse_oid__init(
struct filter *filter)
{
struct filter_sparse_data *d = xcalloc(1, sizeof(*d));
- if (add_patterns_from_blob_to_list(filter_options->sparse_oid_value,
- NULL, 0, &d->pl) < 0)
- die("could not load filter specification");
+ struct object_context oc;
+ struct object_id sparse_oid;
+
+ if (get_oid_with_context(the_repository,
+ filter_options->sparse_oid_name,
+ GET_OID_BLOB, &sparse_oid, &oc))
+ die(_("unable to access sparse blob in '%s'"),
+ filter_options->sparse_oid_name);
+ if (add_patterns_from_blob_to_list(&sparse_oid, "", 0, &d->pl) < 0)
+ die(_("unable to parse sparse filter data in %s"),
+ oid_to_hex(&sparse_oid));
ALLOC_GROW(d->array_frame, d->nr + 1, d->alloc);
d->array_frame[d->nr].default_match = 0; /* default to include */
diff --git a/t/t5616-partial-clone.sh b/t/t5616-partial-clone.sh
index fc634a56b2..79f7b65f8c 100755
--- a/t/t5616-partial-clone.sh
+++ b/t/t5616-partial-clone.sh
@@ -260,6 +260,42 @@ test_expect_success 'fetch what is specified on CLI even if already promised' '
! grep "?$(cat blob)" missing_after
'
+test_expect_success 'setup src repo for sparse filter' '
+ git init sparse-src &&
+ git -C sparse-src config --local uploadpack.allowfilter 1 &&
+ git -C sparse-src config --local uploadpack.allowanysha1inwant 1 &&
+ test_commit -C sparse-src one &&
+ test_commit -C sparse-src two &&
+ echo /one.t >sparse-src/only-one &&
+ git -C sparse-src add . &&
+ git -C sparse-src commit -m "add sparse checkout files"
+'
+
+test_expect_success 'partial clone with sparse filter succeeds' '
+ rm -rf dst.git &&
+ git clone --no-local --bare \
+ --filter=sparse:oid=master:only-one \
+ sparse-src dst.git &&
+ (
+ cd dst.git &&
+ git rev-list --objects --missing=print HEAD >out &&
+ grep "^$(git rev-parse HEAD:one.t)" out &&
+ grep "^?$(git rev-parse HEAD:two.t)" out
+ )
+'
+
+test_expect_success 'partial clone with unresolvable sparse filter fails cleanly' '
+ rm -rf dst.git &&
+ test_must_fail git clone --no-local --bare \
+ --filter=sparse:oid=master:no-such-name \
+ sparse-src dst.git 2>err &&
+ test_i18ngrep "unable to access sparse blob in .master:no-such-name" err &&
+ test_must_fail git clone --no-local --bare \
+ --filter=sparse:oid=master \
+ sparse-src dst.git 2>err &&
+ test_i18ngrep "unable to parse sparse filter data in" err
+'
+
. "$TEST_DIRECTORY"/lib-httpd.sh
start_httpd