]> git.ipfire.org Git - thirdparty/git.git/commitdiff
fetch: inherit filter-spec from partial clone
authorJeff Hostetler <jeffhost@microsoft.com>
Fri, 8 Dec 2017 15:58:50 +0000 (15:58 +0000)
committerJunio C Hamano <gitster@pobox.com>
Fri, 8 Dec 2017 17:58:52 +0000 (09:58 -0800)
Teach (partial) fetch to inherit the filter-spec used by
the partial clone.  Extend --no-filter to override this
inheritance.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/fetch-pack.c
builtin/fetch.c
builtin/rev-list.c
list-objects-filter-options.c
list-objects-filter-options.h
t/t5616-partial-clone.sh

index cbf503537a9b88cda4137e34dd129aec97a3db82..a7bc1366ab375765c41014640743ef9d77c84c42 100644 (file)
@@ -158,7 +158,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
                        continue;
                }
                if (!strcmp(arg, ("--no-" CL_ARG__FILTER))) {
-                       list_objects_filter_release(&args.filter_options);
+                       list_objects_filter_set_no_filter(&args.filter_options);
                        continue;
                }
                usage(fetch_pack_usage);
index 14aab71c2ce0695aaad16ff4f59641d2e11265ef..79c866c225f0f846f3e80547bbe7fe7bf760a45f 100644 (file)
@@ -1275,6 +1275,56 @@ static int fetch_multiple(struct string_list *list)
        return result;
 }
 
+/*
+ * Fetching from the promisor remote should use the given filter-spec
+ * or inherit the default filter-spec from the config.
+ */
+static inline void fetch_one_setup_partial(struct remote *remote)
+{
+       /*
+        * Explicit --no-filter argument overrides everything, regardless
+        * of any prior partial clones and fetches.
+        */
+       if (filter_options.no_filter)
+               return;
+
+       /*
+        * If no prior partial clone/fetch and the current fetch DID NOT
+        * request a partial-fetch, do a normal fetch.
+        */
+       if (!repository_format_partial_clone && !filter_options.choice)
+               return;
+
+       /*
+        * If this is the FIRST partial-fetch request, we enable partial
+        * on this repo and remember the given filter-spec as the default
+        * for subsequent fetches to this remote.
+        */
+       if (!repository_format_partial_clone && filter_options.choice) {
+               partial_clone_register(remote->name, &filter_options);
+               return;
+       }
+
+       /*
+        * We are currently limited to only ONE promisor remote and only
+        * allow partial-fetches from the promisor remote.
+        */
+       if (strcmp(remote->name, repository_format_partial_clone)) {
+               if (filter_options.choice)
+                       die(_("--filter can only be used with the remote configured in core.partialClone"));
+               return;
+       }
+
+       /*
+        * Do a partial-fetch from the promisor remote using either the
+        * explicitly given filter-spec or inherit the filter-spec from
+        * the config.
+        */
+       if (!filter_options.choice)
+               partial_clone_get_default_filter_spec(&filter_options);
+       return;
+}
+
 static int fetch_one(struct remote *remote, int argc, const char **argv)
 {
        static const char **refs = NULL;
@@ -1404,13 +1454,13 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
        }
 
        if (remote) {
-               if (filter_options.choice &&
-                   strcmp(remote->name, repository_format_partial_clone))
-                       die(_("--filter can only be used with the remote configured in core.partialClone"));
+               if (filter_options.choice || repository_format_partial_clone)
+                       fetch_one_setup_partial(remote);
                result = fetch_one(remote, argc, argv);
        } else {
                if (filter_options.choice)
                        die(_("--filter can only be used with the remote configured in core.partialClone"));
+               /* TODO should this also die if we have a previous partial-clone? */
                result = fetch_multiple(&list);
        }
 
index 48f922d7094f4e8e4a3215a2a16c318a82145616..8503dea42dafeb4899cc82d3f06b5d31f71ed996 100644 (file)
@@ -460,7 +460,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
                        continue;
                }
                if (!strcmp(arg, ("--no-" CL_ARG__FILTER))) {
-                       list_objects_filter_release(&filter_options);
+                       list_objects_filter_set_no_filter(&filter_options);
                        continue;
                }
                if (!strcmp(arg, "--filter-print-omitted")) {
index 5c47e2b00243c1751428193ff4453a073d44e6c2..6a3cc985c45e751dd0c3f37880cf0bfd205ef088 100644 (file)
@@ -94,7 +94,7 @@ int opt_parse_list_objects_filter(const struct option *opt,
        struct list_objects_filter_options *filter_options = opt->value;
 
        if (unset || !arg) {
-               list_objects_filter_release(filter_options);
+               list_objects_filter_set_no_filter(filter_options);
                return 0;
        }
 
index 11435392c2f96d635e039e5f287ea60105c1325f..0000a61f82d3dcc36e190b5422a13c93d47f15c2 100644 (file)
@@ -30,6 +30,11 @@ struct list_objects_filter_options {
         */
        enum list_objects_filter_choice choice;
 
+       /*
+        * Choice is LOFC_DISABLED because "--no-filter" was requested.
+        */
+       unsigned int no_filter : 1;
+
        /*
         * Parsed values (fields) from within the filter-spec.  These are
         * choice-specific; not all values will be defined for any given
@@ -58,6 +63,13 @@ int opt_parse_list_objects_filter(const struct option *opt,
 void list_objects_filter_release(
        struct list_objects_filter_options *filter_options);
 
+static inline void list_objects_filter_set_no_filter(
+       struct list_objects_filter_options *filter_options)
+{
+       list_objects_filter_release(filter_options);
+       filter_options->no_filter = 1;
+}
+
 void partial_clone_register(
        const char *remote,
        const struct list_objects_filter_options *filter_options);
index 3b8cc0bba2d49e6675a288b7efc50c138feddbd1..433e07e0cba72e1d93396e5b2f8df311c3741dfc 100755 (executable)
@@ -59,7 +59,7 @@ test_expect_success 'push new commits to server' '
        git -C src remote add srv "file://$(pwd)/srv.bare" &&
        for x in a b c d e
        do
-               echo "Mod $x" >>src/file.1.txt
+               echo "Mod file.1.txt $x" >>src/file.1.txt
                git -C src add file.1.txt
                git -C src commit -m "mod $x"
        done &&
@@ -93,4 +93,24 @@ test_expect_success 'verify blame causes dynamic object fetch' '
        test_line_count = 0 observed
 '
 
+# create new commits in "src" repo to establish a history on file.2.txt
+# and push to "srv.bare".
+test_expect_success 'push new commits to server for file.2.txt' '
+       for x in a b c d e f
+       do
+               echo "Mod file.2.txt $x" >>src/file.2.txt
+               git -C src add file.2.txt
+               git -C src commit -m "mod $x"
+       done &&
+       git -C src push -u srv master
+'
+
+# Do FULL fetch by disabling filter-spec using --no-filter.
+# Verify we have all the new blobs.
+test_expect_success 'override inherited filter-spec using --no-filter' '
+       git -C pc1 fetch --no-filter origin &&
+       git -C pc1 rev-list master..origin/master --quiet --objects --missing=print >observed &&
+       test_line_count = 0 observed
+'
+
 test_done