git/builtin/refs.c
Patrick Steinhardt 25a0023f28 builtin/refs: new command to migrate ref storage formats
Introduce a new command that allows the user to migrate a repository
between ref storage formats. This new command is implemented as part of
a new git-refs(1) executable. This is due to two reasons:

  - There is no good place to put the migration logic in existing
    commands. git-maintenance(1) felt unwieldy, and git-pack-refs(1) is
    not the correct place to put it, either.

  - I had it in my mind to create a new low-level command for accessing
    refs for quite a while already. git-refs(1) is that command and can
    over time grow more functionality relating to refs. This should help
    discoverability by consolidating low-level access to refs into a
    single executable.

As mentioned in the preceding commit that introduces the ref storage
format migration logic, the new `git refs migrate` command still has a
bunch of restrictions. These restrictions are documented accordingly.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-06-06 09:04:34 -07:00

75 lines
1.8 KiB
C

#include "builtin.h"
#include "parse-options.h"
#include "refs.h"
#include "repository.h"
#include "strbuf.h"
#define REFS_MIGRATE_USAGE \
N_("git refs migrate --ref-format=<format> [--dry-run]")
static int cmd_refs_migrate(int argc, const char **argv, const char *prefix)
{
const char * const migrate_usage[] = {
REFS_MIGRATE_USAGE,
NULL,
};
const char *format_str = NULL;
enum ref_storage_format format;
unsigned int flags = 0;
struct option options[] = {
OPT_STRING_F(0, "ref-format", &format_str, N_("format"),
N_("specify the reference format to convert to"),
PARSE_OPT_NONEG),
OPT_BIT(0, "dry-run", &flags,
N_("perform a non-destructive dry-run"),
REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN),
OPT_END(),
};
struct strbuf errbuf = STRBUF_INIT;
int err;
argc = parse_options(argc, argv, prefix, options, migrate_usage, 0);
if (argc)
usage(_("too many arguments"));
if (!format_str)
usage(_("missing --ref-format=<format>"));
format = ref_storage_format_by_name(format_str);
if (format == REF_STORAGE_FORMAT_UNKNOWN) {
err = error(_("unknown ref storage format '%s'"), format_str);
goto out;
}
if (the_repository->ref_storage_format == format) {
err = error(_("repository already uses '%s' format"),
ref_storage_format_to_name(format));
goto out;
}
if (repo_migrate_ref_storage_format(the_repository, format, flags, &errbuf) < 0) {
err = error("%s", errbuf.buf);
goto out;
}
err = 0;
out:
strbuf_release(&errbuf);
return err;
}
int cmd_refs(int argc, const char **argv, const char *prefix)
{
const char * const refs_usage[] = {
REFS_MIGRATE_USAGE,
NULL,
};
parse_opt_subcommand_fn *fn = NULL;
struct option opts[] = {
OPT_SUBCOMMAND("migrate", &fn, cmd_refs_migrate),
OPT_END(),
};
argc = parse_options(argc, argv, prefix, opts, refs_usage, 0);
return fn(argc, argv, prefix);
}