Merge branch 'ds/partial-bundles'
Bundle file format gets extended to allow a partial bundle, filtered by similar criteria you would give when making a partial/lazy clone. * ds/partial-bundles: clone: fail gracefully when cloning filtered bundle bundle: unbundle promisor packs bundle: create filtered bundles rev-list: move --filter parsing into revision.c bundle: parse filter capability list-objects: handle NULL function pointers MyFirstObjectWalk: update recommended usage list-objects: consolidate traverse_commit_list[_filtered] pack-bitmap: drop filter in prepare_bitmap_walk() pack-objects: use rev.filter when possible revision: put object filter into struct rev_info list-objects-filter-options: create copy helper index-pack: document and test the --promisor option
This commit is contained in:
74
bundle.c
74
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,12 @@ int verify_bundle(struct repository *r,
|
||||
r->nr),
|
||||
(uintmax_t)r->nr);
|
||||
list_refs(r, 0, NULL);
|
||||
|
||||
if (header->filter.choice) {
|
||||
printf_ln("The bundle uses this filter: %s",
|
||||
list_objects_filter_spec(&header->filter));
|
||||
}
|
||||
|
||||
r = &header->prerequisites;
|
||||
if (!r->nr) {
|
||||
printf_ln(_("The bundle records a complete history."));
|
||||
@ -319,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;
|
||||
@ -486,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;
|
||||
@ -512,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 */
|
||||
@ -544,6 +584,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 +620,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);
|
||||
|
Reference in New Issue
Block a user