Re: [PATCH 5/5] bundle: generate packfiles via the object database

Junio C Hamano <[email protected]>
Newsgroups org.kernel.vger.git
Message-ID <[email protected]>
Patrick Steinhardt <[email protected]> writes:

> git-bundle(1) spawns git-pack-objects(1) directly to generate the pack
> data that gets appended to the bundle header. While bundles are not
> part of the wire protocol, they are a transfer mechanism for packs all
> the same, so convert them to use the pack generation interface of the
> object database as well.
>
> This makes the pack generator the single spawn point for all pack
> streams that leave the repository, leaving only local maintenance tasks
> like git-repack(1) with direct knowledge of git-pack-objects(1).

Nice to see that the series aims for completeness.

> diff --git a/builtin/bundle.c b/builtin/bundle.c
> index bfafadc984..de86e092a6 100644
> --- a/builtin/bundle.c
> +++ b/builtin/bundle.c
> @@ -69,7 +69,6 @@ static int parse_options_cmd_bundle(int argc,
>  
>  static int cmd_bundle_create(int argc, const char **argv, const char *prefix,
>  			     struct repository *repo UNUSED) {
> -	struct strvec pack_opts = STRVEC_INIT;
>  	int progress = isatty(STDERR_FILENO);
>  	int version = -1;
>  	struct option options[] = {
> @@ -92,16 +91,9 @@ static int cmd_bundle_create(int argc, const char **argv, const char *prefix,
>  			builtin_bundle_create_usage, options, &bundle_file);
>  	/* bundle internals use argv[1] as further parameters */
>  
> -	if (progress)
> -		strvec_push(&pack_opts, "--progress");
> -	else
> -		strvec_push(&pack_opts, "--quiet");
> -	strvec_push(&pack_opts, "--all-progress-implied");
> -
>  	if (!startup_info->have_repository)
>  		die(_("Need a repository to create a bundle."));
> -	ret = !!create_bundle(the_repository, bundle_file, argc, argv, &pack_opts, version);
> -	strvec_clear(&pack_opts);
> +	ret = !!create_bundle(the_repository, bundle_file, argc, argv, version, progress);
>  	free(bundle_file);
>  	return ret;
>  }

At this point after we determined startup_info->have_repository is
true, we should be able to rely on "repo", not "the_repository".
But the callchain starting at the create_bundle() function might not
be ready yet.  Let's keep reading.

> diff --git a/bundle.c b/bundle.c
> index b64716f252..09afc465c0 100644
> --- a/bundle.c
> +++ b/bundle.c
> @@ -325,50 +325,52 @@ static int is_tag_in_date_range(struct object *tag, struct rev_info *revs)
>  
>  
>  /* Write the pack data to bundle_fd */
> -static int write_pack_data(int bundle_fd, struct rev_info *revs, struct strvec *pack_options)
> +static int write_pack_data(int bundle_fd, struct rev_info *revs, int progress)
>  {
> -	struct child_process pack_objects = CHILD_PROCESS_INIT;
> +	struct odb_generate_pack_options opts = ODB_GENERATE_PACK_OPTIONS_INIT;
> +	struct odb_pack_generator *generator;
> +	int ret = 0;
>  	int i;
>  
> -	strvec_pushl(&pack_objects.args,
> -		     "pack-objects",
> -		     "--stdout", "--thin", "--delta-base-offset",
> -		     NULL);
> -	strvec_pushv(&pack_objects.args, pack_options->v);
> +	opts.thin = 1;
> +	opts.ofs_delta = 1;
> +	if (progress)
> +		opts.progress = ODB_GENERATE_PACK_PROGRESS_VERBOSE;
>  	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;
> +		opts.filter_spec = list_objects_filter_spec(&revs->filter);
>  
>  	/*
> -	 * start_command() will close our descriptor if it's >1. Duplicate it
> -	 * to avoid surprising the caller.
> +	 * The pack generator will consume our descriptor if it's >1.
> +	 * Duplicate it to avoid surprising the caller.
>  	 */
> -	if (pack_objects.out > 1) {
> -		pack_objects.out = dup(pack_objects.out);
> -		if (pack_objects.out < 0) {
> -			error_errno(_("unable to dup bundle descriptor"));
> -			child_process_clear(&pack_objects);
> -			return -1;
> -		}
> +	opts.pack_fd = bundle_fd;
> +	if (opts.pack_fd > 1) {
> +		opts.pack_fd = dup(bundle_fd);
> +		if (opts.pack_fd < 0)
> +			return error_errno(_("unable to dup bundle descriptor"));
>  	}
>  
> -	if (start_command(&pack_objects))
> -		return error(_("Could not spawn pack-objects"));
> -
>  	for (i = 0; i < revs->pending.nr; i++) {
>  		struct object *object = revs->pending.objects[i].item;
>  		if (object->flags & UNINTERESTING)
> -			write_or_die(pack_objects.in, "^", 1);
> -		write_or_die(pack_objects.in, oid_to_hex(&object->oid), the_hash_algo->hexsz);
> -		write_or_die(pack_objects.in, "\n", 1);
> +			oid_array_append(&opts.haves, &object->oid);
> +		else
> +			oid_array_append(&opts.wants, &object->oid);
>  	}
> -	close(pack_objects.in);
> -	if (finish_command(&pack_objects))
> -		return error(_("pack-objects died"));
> -	return 0;
> +
> +	if (odb_generate_pack(the_repository->objects, &generator, &opts)) {
> +		ret = error(_("Could not spawn pack-objects"));
> +		goto out;
> +	}
> +
> +	if (odb_pack_generator_finish(generator)) {
> +		ret = error(_("pack-objects died"));
> +		goto out;
> +	}
> +
> +out:
> +	odb_generate_pack_options_release(&opts);
> +	return ret;
>  }

This function uses the_repository, both directly and through
the_hash_algo macro.  I think we could use revs->repo here.  An
obvious alternative is to give this function a new parameter "struct
repository *repo" but then we would have to worry about what should
happen when it and revs->repo go out of sync.

> @@ -476,7 +478,7 @@ static void write_bundle_prerequisites(struct commit *commit, void *data)
>  }
>  
>  int create_bundle(struct repository *r, const char *path,
> -		  int argc, const char **argv, struct strvec *pack_options, int version)
> +		  int argc, const char **argv, int version, int progress)
>  {
>  	struct lock_file lock = LOCK_INIT;
>  	int bundle_fd = -1;
> @@ -584,7 +586,7 @@ int create_bundle(struct repository *r, const char *path,
>  	}
>  
>  	/* write pack */
> -	if (write_pack_data(bundle_fd, &revs_copy, pack_options)) {
> +	if (write_pack_data(bundle_fd, &revs_copy, progress)) {
>  		ret = -1;
>  		goto out;
>  	}
> diff --git a/bundle.h b/bundle.h
> index d664b2f2d6..471da23d1b 100644
> --- a/bundle.h
> +++ b/bundle.h
> @@ -27,8 +27,7 @@ int read_bundle_header(const char *path, struct bundle_header *header);
>  int read_bundle_header_fd(int fd, struct bundle_header *header,
>  			  const char *report_path);
>  int create_bundle(struct repository *r, const char *path,
> -		  int argc, const char **argv, struct strvec *pack_options,
> -		  int version);
> +		  int argc, const char **argv, int version, int progress);
>  
>  enum verify_bundle_flags {
>  	VERIFY_BUNDLE_VERBOSE = (1 << 0),
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.