git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* Empty bundles are not useless
@ 2020-07-14 13:58 R. Lemos
  2020-07-14 21:47 ` Johannes Schindelin
  0 siblings, 1 reply; 2+ messages in thread
From: R. Lemos @ 2020-07-14 13:58 UTC (permalink / raw)
  To: git

When working disconnected (sending bundles back and forth) it is
useful to make bundles like this:

$ git bundle create /tmp/my.bundle master ^disconnected/master

This way I pack all new commits since the last updated from
`disconnected` remote.

But if my local copy is up-to-date, git bundle refuses to create an
empty bundle, since there are no commits to send.

However it would be nice to at least send the information that my
local branch `master` is up-to-date. That is, the bundle would just
convey that my local `master` points to a given commit (even though
this commit is already on the remote site). This way, when I upload
this bundle to the remote site, then bring back changes made there,
the remote site will know which commits I already have.

Thanks.
Rodrigo Lemos

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: Empty bundles are not useless
  2020-07-14 13:58 Empty bundles are not useless R. Lemos
@ 2020-07-14 21:47 ` Johannes Schindelin
  0 siblings, 0 replies; 2+ messages in thread
From: Johannes Schindelin @ 2020-07-14 21:47 UTC (permalink / raw)
  To: R. Lemos; +Cc: git

Hi Rodrigo,

On Tue, 14 Jul 2020, R. Lemos wrote:

> When working disconnected (sending bundles back and forth) it is
> useful to make bundles like this:
>
> $ git bundle create /tmp/my.bundle master ^disconnected/master
>
> This way I pack all new commits since the last updated from
> `disconnected` remote.
>
> But if my local copy is up-to-date, git bundle refuses to create an
> empty bundle, since there are no commits to send.
>
> However it would be nice to at least send the information that my
> local branch `master` is up-to-date. That is, the bundle would just
> convey that my local `master` points to a given commit (even though
> this commit is already on the remote site). This way, when I upload
> this bundle to the remote site, then bring back changes made there,
> the remote site will know which commits I already have.

I am sympathetic to your use case (I certainly had wished for something
like this in the past), but it is not quite as trivial as you might think:
any bundle lists its "wants" and "haves" first, i.e. the commits that it
expects to be present and the tip commits it provides, respectively. And
herein lies the rub: in your case, the tip commit would technically belong
to both "wants" and "haves", and that cannot be represented by the simple
`git rev-list --boundary --pretty=oneline <rev-list-args>` call that
`compute_and_write_prerequisites()` in `bundle.c` performs in order to
generate that wants/haves list.

You could of course implement something in `write_bundle_refs()` that
(guarded by a new option, so as to maintain backwards-compatibility) would
list commits marked as `UNINTERESTING` both as "wants" and "haves", but
that might become a bit tricky e.g. handling commit ranges like
`HEAD~2..HEAD` (where `HEAD~2` would be marked `UNINTERESTING`).

Side note: if it is not clear to you what I mean by `UNINTERESTING`,
please read the excellent tutorial at:
https://github.com/git/git/blob/v2.28.0-rc0/Documentation/MyFirstObjectWalk.txt

Once you worked out how to write out such commits both as prerequisites as
well as refs in the bundle, the rest should be relatively easy: a new test
case in `t/t5607-clone-bundle.sh` to verify that empty bundles can be
created (using a new command-line option that allows precisely that) and
something like this (plus the corresponding docs in
`Documentation/git-bundle.txt`):

-- snip --
diff --git a/bundle.c b/bundle.c
index 99439e07a106..74f2759a2068 100644
--- a/bundle.c
+++ b/bundle.c
@@ -11,6 +11,7 @@
 #include "run-command.h"
 #include "refs.h"
 #include "argv-array.h"
+#include "parse-options.h"

 static const char bundle_signature[] = "# v2 git bundle\n";

@@ -436,6 +437,21 @@ int create_bundle(struct repository *r, const char *path,
 	int bundle_to_stdout;
 	int ref_count = 0;
 	struct rev_info revs;
+	int allow_empty_bundle = 0;
+	struct option options[] = {
+		OPT_BOOL(0, "allow-empty-bundle",
+			 &allow_empty_bundle,
+			 N_("allow an empty bundle to be created")),
+		OPT_END()
+	};
+	const char * const create_usage[] = {
+		N_("git bundle create [<options>] <file> <git-rev-list args>"),
+		NULL
+	};
+
+	argc = parse_options(argc, argv, NULL, options, create_usage,
+			     PARSE_OPT_KEEP_DASHDASH | PARSE_OPT_KEEP_ARGV0 |
+			     PARSE_OPT_KEEP_UNKNOWN);

 	bundle_to_stdout = !strcmp(path, "-");
 	if (bundle_to_stdout)
@@ -465,7 +481,7 @@ int create_bundle(struct repository *r, const char *path,
 	object_array_remove_duplicates(&revs.pending);

 	ref_count = write_bundle_refs(bundle_fd, &revs);
-	if (!ref_count)
+	if (!ref_count && !allow_empty_bundle)
 		die(_("Refusing to create empty bundle."));
 	else if (ref_count < 0)
 		goto err;
-- snap --

Hopefully this gets you started with "scratching your own itch".

Ciao,
Johannes

^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2020-07-14 21:47 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-07-14 13:58 Empty bundles are not useless R. Lemos
2020-07-14 21:47 ` Johannes Schindelin

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).