Skip to content

Commit 4fe42f3

Browse files
john-caigitster
authored andcommitted
pack-refs: teach pack-refs --include option
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 826ae79 commit 4fe42f3

File tree

6 files changed

+67
-12
lines changed

6 files changed

+67
-12
lines changed

Documentation/git-pack-refs.txt

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ git-pack-refs - Pack heads and tags for efficient repository access
88
SYNOPSIS
99
--------
1010
[verse]
11-
'git pack-refs' [--all] [--no-prune] [--exclude <pattern>]
11+
'git pack-refs' [--all] [--no-prune] [--include <pattern>] [--exclude <pattern>]
1212

1313
DESCRIPTION
1414
-----------
@@ -60,6 +60,15 @@ with many branches of historical interests.
6060
The command usually removes loose refs under `$GIT_DIR/refs`
6161
hierarchy after packing them. This option tells it not to.
6262

63+
--include <pattern>::
64+
65+
Pack refs based on a `glob(7)` pattern. Repetitions of this option
66+
accumulate inclusion patterns. If a ref is both included in `--include` and
67+
`--exclude`, `--exclude` takes precedence. Using `--include` will preclude all
68+
tags from being included by default. Symbolic refs and broken refs will never
69+
be packed. When used with `--all`, it will be a noop. Use `--no-include` to clear
70+
and reset the list of patterns.
71+
6372
--exclude <pattern>::
6473

6574
Do not pack refs matching the given `glob(7)` pattern. Repetitions of this option
@@ -70,6 +79,9 @@ unpack it.
7079
When used with `--all`, pack only loose refs which do not match any of
7180
the provided `--exclude` patterns.
7281

82+
When used with `--include`, refs provided to `--include`, minus refs that are
83+
provided to `--exclude` will be packed.
84+
7385

7486
BUGS
7587
----

builtin/pack-refs.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,26 @@
77
#include "revision.h"
88

99
static char const * const pack_refs_usage[] = {
10-
N_("git pack-refs [--all] [--no-prune] [--exclude <pattern>]"),
10+
N_("git pack-refs [--all] [--no-prune] [--include <pattern>] [--exclude <pattern>]"),
1111
NULL
1212
};
1313

1414
int cmd_pack_refs(int argc, const char **argv, const char *prefix)
1515
{
1616
unsigned int flags = PACK_REFS_PRUNE;
1717
static struct ref_exclusions excludes = REF_EXCLUSIONS_INIT;
18-
struct pack_refs_opts pack_refs_opts = {.exclusions = &excludes, .flags = flags};
18+
static struct string_list included_refs = STRING_LIST_INIT_NODUP;
19+
struct pack_refs_opts pack_refs_opts = { .exclusions = &excludes,
20+
.includes = &included_refs,
21+
.flags = flags };
1922
static struct string_list option_excluded_refs = STRING_LIST_INIT_NODUP;
2023
struct string_list_item *item;
2124

2225
struct option opts[] = {
2326
OPT_BIT(0, "all", &pack_refs_opts.flags, N_("pack everything"), PACK_REFS_ALL),
2427
OPT_BIT(0, "prune", &pack_refs_opts.flags, N_("prune loose refs (default)"), PACK_REFS_PRUNE),
28+
OPT_STRING_LIST(0, "include", pack_refs_opts.includes, N_("pattern"),
29+
N_("references to include")),
2530
OPT_STRING_LIST(0, "exclude", &option_excluded_refs, N_("pattern"),
2631
N_("references to exclude")),
2732
OPT_END(),
@@ -33,5 +38,11 @@ int cmd_pack_refs(int argc, const char **argv, const char *prefix)
3338
for_each_string_list_item(item, &option_excluded_refs)
3439
add_ref_exclusion(pack_refs_opts.exclusions, item->string);
3540

41+
if (pack_refs_opts.flags & PACK_REFS_ALL)
42+
string_list_append(pack_refs_opts.includes, "*");
43+
44+
if (!pack_refs_opts.includes->nr)
45+
string_list_append(pack_refs_opts.includes, "refs/tags/*");
46+
3647
return refs_pack_refs(get_main_ref_store(the_repository), &pack_refs_opts);
3748
}

refs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ struct worktree;
6666
struct pack_refs_opts {
6767
unsigned int flags;
6868
struct ref_exclusions *exclusions;
69+
struct string_list *includes;
6970
};
7071

7172
const char *refs_resolve_ref_unsafe(struct ref_store *refs,

refs/files-backend.c

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1176,18 +1176,13 @@ static int should_pack_ref(const char *refname,
11761176
const struct object_id *oid, unsigned int ref_flags,
11771177
struct pack_refs_opts *opts)
11781178
{
1179+
struct string_list_item *item;
1180+
11791181
/* Do not pack per-worktree refs: */
11801182
if (parse_worktree_ref(refname, NULL, NULL, NULL) !=
11811183
REF_WORKTREE_SHARED)
11821184
return 0;
11831185

1184-
if (ref_excluded(opts->exclusions, refname))
1185-
return 0;
1186-
1187-
/* Do not pack non-tags unless PACK_REFS_ALL is set: */
1188-
if (!(opts->flags & PACK_REFS_ALL) && !starts_with(refname, "refs/tags/"))
1189-
return 0;
1190-
11911186
/* Do not pack symbolic refs: */
11921187
if (ref_flags & REF_ISSYMREF)
11931188
return 0;
@@ -1196,7 +1191,14 @@ static int should_pack_ref(const char *refname,
11961191
if (!ref_resolves_to_object(refname, the_repository, oid, ref_flags))
11971192
return 0;
11981193

1199-
return 1;
1194+
if (ref_excluded(opts->exclusions, refname))
1195+
return 0;
1196+
1197+
for_each_string_list_item(item, opts->includes)
1198+
if (!wildmatch(item->string, refname, 0))
1199+
return 1;
1200+
1201+
return 0;
12001202
}
12011203

12021204
static int files_pack_refs(struct ref_store *ref_store,

t/helper/test-ref-store.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "worktree.h"
66
#include "object-store.h"
77
#include "repository.h"
8+
#include "revision.h"
89

910
struct flag_definition {
1011
const char *name;
@@ -116,7 +117,14 @@ static struct flag_definition pack_flags[] = { FLAG_DEF(PACK_REFS_PRUNE),
116117
static int cmd_pack_refs(struct ref_store *refs, const char **argv)
117118
{
118119
unsigned int flags = arg_flags(*argv++, "flags", pack_flags);
119-
struct pack_refs_opts pack_opts = { .flags = flags };
120+
static struct ref_exclusions exclusions = REF_EXCLUSIONS_INIT;
121+
static struct string_list included_refs = STRING_LIST_INIT_NODUP;
122+
struct pack_refs_opts pack_opts = { .flags = flags,
123+
.exclusions = &exclusions,
124+
.includes = &included_refs };
125+
126+
if (pack_opts.flags & PACK_REFS_ALL)
127+
string_list_append(pack_opts.includes, "*");
120128

121129
return refs_pack_refs(refs, &pack_opts);
122130
}

t/t3210-pack-refs.sh

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,27 @@ test_expect_success 'test --no-exclude refs clears excluded refs' '
124124
! test -f .git/refs/heads/dont_pack3 &&
125125
! test -f .git/refs/heads/dont_pack4'
126126

127+
test_expect_success 'test only included refs are packed' '
128+
git branch pack_this1 &&
129+
git branch pack_this2 &&
130+
git tag dont_pack5 &&
131+
git pack-refs --include "refs/heads/pack_this*" &&
132+
test -f .git/refs/tags/dont_pack5 &&
133+
! test -f .git/refs/heads/pack_this1 &&
134+
! test -f .git/refs/heads/pack_this2'
135+
136+
test_expect_success 'test --no-include refs clears included refs' '
137+
git branch pack1 &&
138+
git branch pack2 &&
139+
git pack-refs --include "refs/heads/pack*" --no-include &&
140+
test -f .git/refs/heads/pack1 &&
141+
test -f .git/refs/heads/pack2'
142+
143+
test_expect_success 'test --exclude takes precedence over --include' '
144+
git branch dont_pack5 &&
145+
git pack-refs --include "refs/heads/pack*" --exclude "refs/heads/pack*" &&
146+
test -f .git/refs/heads/dont_pack5'
147+
127148
test_expect_success \
128149
'see if up-to-date packed refs are preserved' \
129150
'git branch q &&

0 commit comments

Comments
 (0)