]> git.ipfire.org Git - thirdparty/git.git/blobdiff - bundle.c
revision.[ch]: document and move code declared around "init"
[thirdparty/git.git] / bundle.c
index 7608701a51ee2a4a18ea4499cb5eaf1823ef5d44..d50cfb5aa7e9c28afc121f9bf27499518a3fee37 100644 (file)
--- a/bundle.c
+++ b/bundle.c
@@ -11,7 +11,7 @@
 #include "run-command.h"
 #include "refs.h"
 #include "strvec.h"
-
+#include "list-objects-filter-options.h"
 
 static const char v2_bundle_signature[] = "# v2 git bundle\n";
 static const char v3_bundle_signature[] = "# v3 git bundle\n";
@@ -33,6 +33,7 @@ void bundle_header_release(struct bundle_header *header)
 {
        string_list_clear(&header->prerequisites, 1);
        string_list_clear(&header->references, 1);
+       list_objects_filter_release(&header->filter);
 }
 
 static int parse_capability(struct bundle_header *header, const char *capability)
@@ -45,6 +46,10 @@ static int parse_capability(struct bundle_header *header, const char *capability
                header->hash_algo = &hash_algos[algo];
                return 0;
        }
+       if (skip_prefix(capability, "filter=", &arg)) {
+               parse_list_objects_filter(&header->filter, arg);
+               return 0;
+       }
        return error(_("unknown capability '%s'"), capability);
 }
 
@@ -220,6 +225,8 @@ int verify_bundle(struct repository *r,
        req_nr = revs.pending.nr;
        setup_revisions(2, argv, &revs, NULL);
 
+       list_objects_filter_copy(&revs.filter, &header->filter);
+
        if (prepare_revision_walk(&revs))
                die(_("revision walk setup failed"));
 
@@ -259,6 +266,7 @@ int verify_bundle(struct repository *r,
                             r->nr),
                          (uintmax_t)r->nr);
                list_refs(r, 0, NULL);
+
                r = &header->prerequisites;
                if (!r->nr) {
                        printf_ln(_("The bundle records a complete history."));
@@ -269,6 +277,12 @@ int verify_bundle(struct repository *r,
                                  (uintmax_t)r->nr);
                        list_refs(r, 0, NULL);
                }
+
+               printf_ln("The bundle uses this hash algorithm: %s",
+                         header->hash_algo->name);
+               if (header->filter.choice)
+                       printf_ln("The bundle uses this filter: %s",
+                                 list_objects_filter_spec(&header->filter));
        }
        return ret;
 }
@@ -319,6 +333,9 @@ static int write_pack_data(int bundle_fd, struct rev_info *revs, struct strvec *
                     "--stdout", "--thin", "--delta-base-offset",
                     NULL);
        strvec_pushv(&pack_objects.args, pack_options->v);
+       if (revs->filter.choice)
+               strvec_pushf(&pack_objects.args, "--filter=%s",
+                            list_objects_filter_spec(&revs->filter));
        pack_objects.in = -1;
        pack_objects.out = bundle_fd;
        pack_objects.git_cmd = 1;
@@ -486,10 +503,37 @@ int create_bundle(struct repository *r, const char *path,
        int bundle_to_stdout;
        int ref_count = 0;
        struct rev_info revs, revs_copy;
-       int min_version = the_hash_algo == &hash_algos[GIT_HASH_SHA1] ? 2 : 3;
+       int min_version = 2;
        struct bundle_prerequisites_info bpi;
        int i;
 
+       /* init revs to list objects for pack-objects later */
+       save_commit_buffer = 0;
+       repo_init_revisions(r, &revs, NULL);
+
+       /*
+        * Pre-initialize the '--objects' flag so we can parse a
+        * --filter option successfully.
+        */
+       revs.tree_objects = revs.blob_objects = 1;
+
+       argc = setup_revisions(argc, argv, &revs, NULL);
+
+       /*
+        * Reasons to require version 3:
+        *
+        * 1. @object-format is required because our hash algorithm is not
+        *    SHA1.
+        * 2. @filter is required because we parsed an object filter.
+        */
+       if (the_hash_algo != &hash_algos[GIT_HASH_SHA1] || revs.filter.choice)
+               min_version = 3;
+
+       if (argc > 1) {
+               error(_("unrecognized argument: %s"), argv[1]);
+               goto err;
+       }
+
        bundle_to_stdout = !strcmp(path, "-");
        if (bundle_to_stdout)
                bundle_fd = 1;
@@ -512,17 +556,14 @@ int create_bundle(struct repository *r, const char *path,
                write_or_die(bundle_fd, capability, strlen(capability));
                write_or_die(bundle_fd, the_hash_algo->name, strlen(the_hash_algo->name));
                write_or_die(bundle_fd, "\n", 1);
-       }
 
-       /* init revs to list objects for pack-objects later */
-       save_commit_buffer = 0;
-       repo_init_revisions(r, &revs, NULL);
-
-       argc = setup_revisions(argc, argv, &revs, NULL);
-
-       if (argc > 1) {
-               error(_("unrecognized argument: %s"), argv[1]);
-               goto err;
+               if (revs.filter.choice) {
+                       const char *value = expand_list_objects_filter_spec(&revs.filter);
+                       capability = "@filter=";
+                       write_or_die(bundle_fd, capability, strlen(capability));
+                       write_or_die(bundle_fd, value, strlen(value));
+                       write_or_die(bundle_fd, "\n", 1);
+               }
        }
 
        /* save revs.pending in revs_copy for later use */
@@ -544,6 +585,12 @@ int create_bundle(struct repository *r, const char *path,
                die("revision walk setup failed");
        bpi.fd = bundle_fd;
        bpi.pending = &revs_copy.pending;
+
+       /*
+        * Remove any object walking here. We only care about commits and
+        * tags here. The revs_copy has the right instances of these values.
+        */
+       revs.blob_objects = revs.tree_objects = 0;
        traverse_commit_list(&revs, write_bundle_prerequisites, NULL, &bpi);
        object_array_remove_duplicates(&revs_copy.pending);
 
@@ -574,6 +621,10 @@ int unbundle(struct repository *r, struct bundle_header *header,
        struct child_process ip = CHILD_PROCESS_INIT;
        strvec_pushl(&ip.args, "index-pack", "--fix-thin", "--stdin", NULL);
 
+       /* If there is a filter, then we need to create the promisor pack. */
+       if (header->filter.choice)
+               strvec_push(&ip.args, "--promisor=from-bundle");
+
        if (extra_index_pack_args) {
                strvec_pushv(&ip.args, extra_index_pack_args->v);
                strvec_clear(extra_index_pack_args);