All of lore.kernel.org
 help / color / mirror / Atom feed
From: "John Cai via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: Junio C Hamano <gitster@pobox.com>,
	Christian Couder <christian.couder@gmail.com>,
	John Cai <johncai86@gmail.com>, John Cai <johncai86@gmail.com>
Subject: [PATCH v3 4/4] pack-refs: teach pack-refs --include option
Date: Thu, 11 May 2023 18:10:34 +0000	[thread overview]
Message-ID: <b2f3b98cd2461a25ab708adbcd8a95f5e2b18e5e.1683828635.git.gitgitgadget@gmail.com> (raw)
In-Reply-To: <pull.1501.v3.git.git.1683828635.gitgitgadget@gmail.com>

From: John Cai <johncai86@gmail.com>

Allow users to be more selective over which refs to pack by adding an
--include option to git-pack-refs.

The existing options allow some measure of selectivity. By default
git-pack-refs packs all tags. --all can be used to include all refs,
and the previous commit added the ability to exclude certain refs with
--exclude.

While these knobs give the user some selection over which refs to pack,
it could be useful to give more control. For instance, a repository may
have a set of branches that are rarely updated and would benefit from
being packed. --include would allow the user to easily include a set of
branches to be packed while leaving everything else unpacked.

Signed-off-by: John Cai <johncai86@gmail.com>
---
 Documentation/git-pack-refs.txt | 14 +++++++++++++-
 builtin/pack-refs.c             | 18 ++++++++++++++++--
 refs/files-backend.c            | 15 +++++++--------
 t/helper/test-ref-store.c       |  8 +++++++-
 t/t3210-pack-refs.sh            | 21 +++++++++++++++++++++
 5 files changed, 64 insertions(+), 12 deletions(-)

diff --git a/Documentation/git-pack-refs.txt b/Documentation/git-pack-refs.txt
index c0f7426e519..85874a5f5dc 100644
--- a/Documentation/git-pack-refs.txt
+++ b/Documentation/git-pack-refs.txt
@@ -8,7 +8,7 @@ git-pack-refs - Pack heads and tags for efficient repository access
 SYNOPSIS
 --------
 [verse]
-'git pack-refs' [--all] [--no-prune] [--exclude <pattern>]
+'git pack-refs' [--all] [--no-prune] [--include <pattern>] [--exclude <pattern>]
 
 DESCRIPTION
 -----------
@@ -60,6 +60,15 @@ interests.
 The command usually removes loose refs under `$GIT_DIR/refs`
 hierarchy after packing them.  This option tells it not to.
 
+--include <pattern>::
+
+Pack refs based on a `glob(7)` pattern. Repetitions of this option
+accumulate inclusion patterns. If a ref is both included in `--include` and
+`--exclude`, `--exclude` takes precedence. Using `--include` will preclude all
+tags from being included by default. Symbolic refs and broken refs will never
+be packed. When used with `--all`, it will be a noop. Use `--no-include` to clear
+and reset the list of patterns.
+
 --exclude <pattern>::
 
 Do not pack refs matching the given `glob(7)` pattern. Repetitions of this option
@@ -70,6 +79,9 @@ unpack it.
 When used with `--all`, it will use the difference between the set of all refs,
 and what is provided to `--exclude`.
 
+When used with `--include`, refs provided to `--include`, minus refs that are
+provided to `--exclude` will be packed.
+
 
 BUGS
 ----
diff --git a/builtin/pack-refs.c b/builtin/pack-refs.c
index 2464575a665..5062206f22e 100644
--- a/builtin/pack-refs.c
+++ b/builtin/pack-refs.c
@@ -5,9 +5,10 @@
 #include "refs.h"
 #include "repository.h"
 #include "revision.h"
+#include "trace.h"
 
 static char const * const pack_refs_usage[] = {
-	N_("git pack-refs [--all] [--no-prune] [--exclude <pattern>]"),
+	N_("git pack-refs [--all] [--no-prune] [--include <pattern>] [--exclude <pattern>]"),
 	NULL
 };
 
@@ -15,13 +16,17 @@ int cmd_pack_refs(int argc, const char **argv, const char *prefix)
 {
 	unsigned int flags = PACK_REFS_PRUNE;
 	static struct ref_visibility visibility = REF_VISIBILITY_INIT;
-	struct pack_refs_opts pack_refs_opts = {.visibility = &visibility, .flags = flags};
+	struct pack_refs_opts pack_refs_opts = { .visibility = &visibility,
+						 .flags = flags };
 	static struct string_list option_excluded_refs = STRING_LIST_INIT_NODUP;
+	static struct string_list option_included_refs = STRING_LIST_INIT_NODUP;
 	struct string_list_item *item;
 
 	struct option opts[] = {
 		OPT_BIT(0, "all",   &pack_refs_opts.flags, N_("pack everything"), PACK_REFS_ALL),
 		OPT_BIT(0, "prune", &pack_refs_opts.flags, N_("prune loose refs (default)"), PACK_REFS_PRUNE),
+		OPT_STRING_LIST(0, "include", &option_included_refs, N_("pattern"),
+			N_("references to include")),
 		OPT_STRING_LIST(0, "exclude", &option_excluded_refs, N_("pattern"),
 			N_("references to exclude")),
 		OPT_END(),
@@ -33,5 +38,14 @@ int cmd_pack_refs(int argc, const char **argv, const char *prefix)
 	for_each_string_list_item(item, &option_excluded_refs)
 		add_ref_exclusion(pack_refs_opts.visibility, item->string);
 
+	for_each_string_list_item(item, &option_included_refs)
+		add_ref_inclusion(pack_refs_opts.visibility, item->string);
+
+	if (pack_refs_opts.flags & PACK_REFS_ALL)
+		add_ref_inclusion(pack_refs_opts.visibility, "*");
+
+	if (!pack_refs_opts.visibility->included_refs.nr)
+		add_ref_inclusion(pack_refs_opts.visibility, "refs/tags/*");
+
 	return refs_pack_refs(get_main_ref_store(the_repository), &pack_refs_opts);
 }
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 3ef19199788..c669cf8001a 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -1183,13 +1183,6 @@ static int should_pack_ref(const char *refname,
 	    REF_WORKTREE_SHARED)
 		return 0;
 
-	if (opts->visibility && ref_excluded(opts->visibility, refname))
-		return 0;
-
-	/* Do not pack non-tags unless PACK_REFS_ALL is set: */
-	if (!(opts->flags & PACK_REFS_ALL) && !starts_with(refname, "refs/tags/"))
-		return 0;
-
 	/* Do not pack symbolic refs: */
 	if (ref_flags & REF_ISSYMREF)
 		return 0;
@@ -1198,7 +1191,13 @@ static int should_pack_ref(const char *refname,
 	if (!ref_resolves_to_object(refname, the_repository, oid, ref_flags))
 		return 0;
 
-	return 1;
+	if (opts->visibility && ref_excluded(opts->visibility, refname))
+		return 0;
+
+	if (opts->visibility && ref_included(opts->visibility, refname))
+		return 1;
+
+	return 0;
 }
 
 static int files_pack_refs(struct ref_store *ref_store,
diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c
index de4197708d9..0dec1223362 100644
--- a/t/helper/test-ref-store.c
+++ b/t/helper/test-ref-store.c
@@ -5,6 +5,7 @@
 #include "worktree.h"
 #include "object-store.h"
 #include "repository.h"
+#include "revision.h"
 
 struct flag_definition {
 	const char *name;
@@ -116,7 +117,12 @@ static struct flag_definition pack_flags[] = { FLAG_DEF(PACK_REFS_PRUNE),
 static int cmd_pack_refs(struct ref_store *refs, const char **argv)
 {
 	unsigned int flags = arg_flags(*argv++, "flags", pack_flags);
-	struct pack_refs_opts pack_opts = { .flags = flags };
+	static struct ref_visibility visibility = REF_VISIBILITY_INIT;
+	struct pack_refs_opts pack_opts = { .flags = flags,
+					    .visibility = &visibility };
+
+	if (pack_opts.flags & PACK_REFS_ALL)
+		add_ref_inclusion(pack_opts.visibility, "*");
 
 	return refs_pack_refs(refs, &pack_opts);
 }
diff --git a/t/t3210-pack-refs.sh b/t/t3210-pack-refs.sh
index ddfc1b6e5f1..9ff6326b646 100755
--- a/t/t3210-pack-refs.sh
+++ b/t/t3210-pack-refs.sh
@@ -124,6 +124,27 @@ test_expect_success 'test --no-exclude refs clears excluded refs' '
 	! test -f .git/refs/heads/dont_pack3 &&
 	! test -f .git/refs/heads/dont_pack4'
 
+test_expect_success 'test only included refs are packed' '
+	git branch pack_this1 &&
+	git branch pack_this2 &&
+	git tag dont_pack5 &&
+	git pack-refs --include "refs/heads/pack_this*" &&
+	test -f .git/refs/tags/dont_pack5 &&
+	! test -f ./git/refs/heads/pack_this1 &&
+	! test -f ./git/refs/heads/pack_this2'
+
+test_expect_success 'test --no-include refs clears included refs' '
+	git branch pack1 &&
+	git branch pack2 &&
+	git pack-refs --include "refs/heads/pack*" --no-include &&
+	test -f .git/refs/heads/pack1 &&
+	test -f .git/refs/heads/pack2'
+
+test_expect_success 'test --exclude takes precedence over --include' '
+	git branch dont_pack5 &&
+	git pack-refs --include "refs/heads/pack*" --exclude "refs/heads/pack*" &&
+	test -f .git/refs/heads/dont_pack5'
+
 test_expect_success \
 	'see if up-to-date packed refs are preserved' \
 	'git branch q &&
-- 
gitgitgadget

  parent reply	other threads:[~2023-05-11 18:11 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-05-04 15:48 [PATCH] pack-refs: teach --exclude option to exclude refs from being packed John Cai via GitGitGadget
2023-05-04 16:48 ` Junio C Hamano
2023-05-04 21:26   ` John Cai
2023-05-09 19:18 ` [PATCH v2 0/3] pack-refs: Teach " John Cai via GitGitGadget
2023-05-09 19:18   ` [PATCH v2 1/3] docs: clarify git-pack-refs --all will pack all refs John Cai via GitGitGadget
2023-05-09 19:18   ` [PATCH v2 2/3] pack-refs: teach --exclude option to exclude refs from being packed John Cai via GitGitGadget
2023-05-09 21:04     ` Junio C Hamano
2023-05-09 19:18   ` [PATCH v2 3/3] pack-refs: teach pack-refs --include option John Cai via GitGitGadget
2023-05-09 21:25     ` Junio C Hamano
2023-05-10 19:52       ` John Cai
2023-05-11 18:10   ` [PATCH v3 0/4] pack-refs: allow users control over which refs to pack John Cai via GitGitGadget
2023-05-11 18:10     ` [PATCH v3 1/4] docs: clarify git-pack-refs --all will pack all refs John Cai via GitGitGadget
2023-05-11 23:53       ` Taylor Blau
2023-05-11 18:10     ` [PATCH v3 2/4] pack-refs: teach --exclude option to exclude refs from being packed John Cai via GitGitGadget
2023-05-11 19:34       ` Junio C Hamano
2023-05-12  0:00       ` Taylor Blau
2023-05-12 12:53         ` John Cai
2023-05-12 21:11           ` John Cai
2023-05-11 18:10     ` [PATCH v3 3/4] revision: modify ref_exclusions to handle inclusions John Cai via GitGitGadget
2023-05-11 19:54       ` Junio C Hamano
2023-05-12 14:56         ` John Cai
2023-05-11 18:10     ` John Cai via GitGitGadget [this message]
2023-05-11 20:06       ` [PATCH v3 4/4] pack-refs: teach pack-refs --include option Junio C Hamano
2023-05-12 14:48         ` John Cai
2023-05-12 19:03       ` John Cai
2023-05-12 21:34     ` [PATCH v4 0/3] pack-refs: allow users control over which refs to pack John Cai via GitGitGadget
2023-05-12 21:34       ` [PATCH v4 1/3] docs: clarify git-pack-refs --all will pack all refs John Cai via GitGitGadget
2023-05-12 21:34       ` [PATCH v4 2/3] pack-refs: teach --exclude option to exclude refs from being packed John Cai via GitGitGadget
2023-05-12 21:34       ` [PATCH v4 3/3] pack-refs: teach pack-refs --include option John Cai via GitGitGadget

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=b2f3b98cd2461a25ab708adbcd8a95f5e2b18e5e.1683828635.git.gitgitgadget@gmail.com \
    --to=gitgitgadget@gmail.com \
    --cc=christian.couder@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=johncai86@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.