Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.kernel.org/pub/scm/git/git.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bundle.c53
-rwxr-xr-xt/t6020-bundle-misc.sh48
2 files changed, 90 insertions, 11 deletions
diff --git a/bundle.c b/bundle.c
index 41e75efab9..9370a6e307 100644
--- a/bundle.c
+++ b/bundle.c
@@ -332,6 +332,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;
@@ -499,10 +502,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;
@@ -525,17 +555,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 */
@@ -558,6 +585,10 @@ int create_bundle(struct repository *r, const char *path,
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);
diff --git a/t/t6020-bundle-misc.sh b/t/t6020-bundle-misc.sh
index df5ff561fa..6e97c044ee 100755
--- a/t/t6020-bundle-misc.sh
+++ b/t/t6020-bundle-misc.sh
@@ -487,4 +487,52 @@ test_expect_success 'unfiltered bundle with --objects' '
test_cmp expect actual
'
+for filter in "blob:none" "tree:0" "tree:1" "blob:limit=100"
+do
+ test_expect_success "filtered bundle: $filter" '
+ test_when_finished rm -rf .git/objects/pack cloned unbundled &&
+ git bundle create partial.bdl \
+ --all \
+ --filter=$filter &&
+
+ git bundle verify partial.bdl >unfiltered &&
+ make_user_friendly_and_stable_output <unfiltered >actual &&
+
+ cat >expect <<-EOF &&
+ The bundle contains these 10 refs:
+ <COMMIT-P> refs/heads/main
+ <COMMIT-N> refs/heads/release
+ <COMMIT-D> refs/heads/topic/1
+ <COMMIT-H> refs/heads/topic/2
+ <COMMIT-D> refs/pull/1/head
+ <COMMIT-G> refs/pull/2/head
+ <TAG-1> refs/tags/v1
+ <TAG-2> refs/tags/v2
+ <TAG-3> refs/tags/v3
+ <COMMIT-P> HEAD
+ The bundle uses this filter: $filter
+ The bundle records a complete history.
+ EOF
+ test_cmp expect actual &&
+
+ test_config uploadpack.allowfilter 1 &&
+ test_config uploadpack.allowanysha1inwant 1 &&
+ git clone --no-local --filter=$filter --bare "file://$(pwd)" cloned &&
+
+ git init unbundled &&
+ git -C unbundled bundle unbundle ../partial.bdl >ref-list.txt &&
+
+ # Count the same number of reachable objects.
+ reflist=$(git for-each-ref --format="%(objectname)") &&
+ git rev-list --objects --filter=$filter --missing=allow-any \
+ $reflist >expect &&
+ for repo in cloned unbundled
+ do
+ git -C $repo rev-list --objects --missing=allow-any \
+ $reflist >actual &&
+ test_cmp expect actual || return 1
+ done
+ '
+done
+
test_done