builtin/pack-refs: factor out core logic into a shared library

The implementation of `git pack-refs` is monolithic within `cmd_pack_refs()`, making it impossible to share its logic with other commands. To enable code reuse for the upcoming `git refs optimize` subcommand, refactor the core logic into a shared helper function. Split the original `builtin/pack-refs.c` file into two parts: - A new shared library file, `pack-refs.c`, which contains the core option parsing and packing logic in a new `pack_refs_core()` helper function. - The original `builtin/pack-refs.c`, which is now a thin wrapper responsible only for defining the `git pack-refs` command and calling the shared helper. A new `pack-refs.h` header is also introduced to define the public interface for this shared logic. Mentored-by: Patrick Steinhardt <ps@pks.im> Mentored-by: shejialuo <shejialuo@gmail.com> Signed-off-by: Meet Soni <meetsoni3017@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Meet Soni committed Sep 19, 2025 at 13:56 UTC 0d4ec339227d04bcba89390bdef22d4dce30d271
5 files changed +86 -49
Makefile
+1
@@ -1094,6 +1094,7 @@ LIB_OBJS += pack-bitmap.o
1094 LIB_OBJS += pack-check.o
1095 LIB_OBJS += pack-mtimes.o
1096 LIB_OBJS += pack-objects.o
1097 +LIB_OBJS += pack-refs.o
1098 LIB_OBJS += pack-revindex.o
1099 LIB_OBJS += pack-write.o
1100 LIB_OBJS += packfile.o
builtin/pack-refs.c
+5 -49
@@ -1,60 +1,16 @@
1 #include "builtin.h"
2 -#include "config.h"
3 -#include "environment.h"
2 #include "gettext.h"
5 -#include "parse-options.h"
6 -#include "refs.h"
7 -#include "revision.h"
8 -
9 -static char const * const pack_refs_usage[] = {
10 - N_("git pack-refs [--all] [--no-prune] [--auto] [--include <pattern>] [--exclude <pattern>]"),
11 - NULL
12 -};
3 +#include "pack-refs.h"
4
5 int cmd_pack_refs(int argc,
6 const char **argv,
7 const char *prefix,
8 struct repository *repo)
9 {
19 - struct ref_exclusions excludes = REF_EXCLUSIONS_INIT;
20 - struct string_list included_refs = STRING_LIST_INIT_NODUP;
21 - struct pack_refs_opts pack_refs_opts = {
22 - .exclusions = &excludes,
23 - .includes = &included_refs,
24 - .flags = PACK_REFS_PRUNE,
25 - };
26 - struct string_list option_excluded_refs = STRING_LIST_INIT_NODUP;
27 - struct string_list_item *item;
28 - int pack_all = 0;
29 - int ret;
30 -
31 - struct option opts[] = {
32 - OPT_BOOL(0, "all", &pack_all, N_("pack everything")),
33 - OPT_BIT(0, "prune", &pack_refs_opts.flags, N_("prune loose refs (default)"), PACK_REFS_PRUNE),
34 - OPT_BIT(0, "auto", &pack_refs_opts.flags, N_("auto-pack refs as needed"), PACK_REFS_AUTO),
35 - OPT_STRING_LIST(0, "include", pack_refs_opts.includes, N_("pattern"),
36 - N_("references to include")),
37 - OPT_STRING_LIST(0, "exclude", &option_excluded_refs, N_("pattern"),
38 - N_("references to exclude")),
39 - OPT_END(),
10 + static char const * const pack_refs_usage[] = {
11 + N_("git pack-refs " PACK_REFS_OPTS),
12 + NULL
13 };
41 - repo_config(repo, git_default_config, NULL);
42 - if (parse_options(argc, argv, prefix, opts, pack_refs_usage, 0))
43 - usage_with_options(pack_refs_usage, opts);
44 -
45 - for_each_string_list_item(item, &option_excluded_refs)
46 - add_ref_exclusion(pack_refs_opts.exclusions, item->string);
47 -
48 - if (pack_all)
49 - string_list_append(pack_refs_opts.includes, "*");
50 -
51 - if (!pack_refs_opts.includes->nr)
52 - string_list_append(pack_refs_opts.includes, "refs/tags/*");
53 -
54 - ret = refs_optimize(get_main_ref_store(repo), &pack_refs_opts);
14
56 - clear_ref_exclusions(&excludes);
57 - string_list_clear(&included_refs, 0);
58 - string_list_clear(&option_excluded_refs, 0);
59 - return ret;
15 + return pack_refs_core(argc, argv, prefix, repo, pack_refs_usage);
16 }
meson.build
+1
@@ -407,6 +407,7 @@ libgit_sources = [
407 'pack-check.c',
408 'pack-mtimes.c',
409 'pack-objects.c',
410 + 'pack-refs.c',
411 'pack-revindex.c',
412 'pack-write.c',
413 'packfile.c',
pack-refs.c new
+56
@@ -0,0 +1,56 @@
1 +#include "builtin.h"
2 +#include "config.h"
3 +#include "environment.h"
4 +#include "pack-refs.h"
5 +#include "parse-options.h"
6 +#include "refs.h"
7 +#include "revision.h"
8 +
9 +int pack_refs_core(int argc,
10 + const char **argv,
11 + const char *prefix,
12 + struct repository *repo,
13 + const char * const *usage_opts)
14 +{
15 + struct ref_exclusions excludes = REF_EXCLUSIONS_INIT;
16 + struct string_list included_refs = STRING_LIST_INIT_NODUP;
17 + struct pack_refs_opts pack_refs_opts = {
18 + .exclusions = &excludes,
19 + .includes = &included_refs,
20 + .flags = PACK_REFS_PRUNE,
21 + };
22 + struct string_list option_excluded_refs = STRING_LIST_INIT_NODUP;
23 + struct string_list_item *item;
24 + int pack_all = 0;
25 + int ret;
26 +
27 + struct option opts[] = {
28 + OPT_BOOL(0, "all", &pack_all, N_("pack everything")),
29 + OPT_BIT(0, "prune", &pack_refs_opts.flags, N_("prune loose refs (default)"), PACK_REFS_PRUNE),
30 + OPT_BIT(0, "auto", &pack_refs_opts.flags, N_("auto-pack refs as needed"), PACK_REFS_AUTO),
31 + OPT_STRING_LIST(0, "include", pack_refs_opts.includes, N_("pattern"),
32 + N_("references to include")),
33 + OPT_STRING_LIST(0, "exclude", &option_excluded_refs, N_("pattern"),
34 + N_("references to exclude")),
35 + OPT_END(),
36 + };
37 + repo_config(repo, git_default_config, NULL);
38 + if (parse_options(argc, argv, prefix, opts, usage_opts, 0))
39 + usage_with_options(usage_opts, opts);
40 +
41 + for_each_string_list_item(item, &option_excluded_refs)
42 + add_ref_exclusion(pack_refs_opts.exclusions, item->string);
43 +
44 + if (pack_all)
45 + string_list_append(pack_refs_opts.includes, "*");
46 +
47 + if (!pack_refs_opts.includes->nr)
48 + string_list_append(pack_refs_opts.includes, "refs/tags/*");
49 +
50 + ret = refs_optimize(get_main_ref_store(repo), &pack_refs_opts);
51 +
52 + clear_ref_exclusions(&excludes);
53 + string_list_clear(&included_refs, 0);
54 + string_list_clear(&option_excluded_refs, 0);
55 + return ret;
56 +}
pack-refs.h new
+23
@@ -0,0 +1,23 @@
1 +#ifndef PACK_REFS_H
2 +#define PACK_REFS_H
3 +
4 +struct repository;
5 +
6 +/*
7 + * Shared usage string for options common to git-pack-refs(1)
8 + * and git-refs-optimize(1). The command-specific part (e.g., "git refs optimize ")
9 + * must be prepended by the caller.
10 + */
11 +#define PACK_REFS_OPTS \
12 + "[--all] [--no-prune] [--auto] [--include <pattern>] [--exclude <pattern>]"
13 +
14 +/*
15 + * The core logic for pack-refs and its clones.
16 + */
17 +int pack_refs_core(int argc,
18 + const char **argv,
19 + const char *prefix,
20 + struct repository *repo,
21 + const char * const *usage_opts);
22 +
23 +#endif /* PACK_REFS_H */