Skip to content

Commit 25a0023

Browse files
pks-tgitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 6d6a3a9 commit 25a0023

File tree

8 files changed

+384
-0
lines changed

8 files changed

+384
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@
126126
/git-rebase
127127
/git-receive-pack
128128
/git-reflog
129+
/git-refs
129130
/git-remote
130131
/git-remote-http
131132
/git-remote-https

Documentation/git-refs.txt

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
git-refs(1)
2+
===========
3+
4+
NAME
5+
----
6+
git-refs - Low-level access to refs
7+
8+
9+
SYNOPSIS
10+
--------
11+
[verse]
12+
'git refs migrate' --ref-format=<format> [--dry-run]
13+
14+
DESCRIPTION
15+
-----------
16+
17+
This command provides low-level access to refs.
18+
19+
COMMANDS
20+
--------
21+
22+
migrate::
23+
Migrate ref store between different formats.
24+
25+
OPTIONS
26+
-------
27+
28+
The following options are specific to 'git refs migrate':
29+
30+
--ref-format=<format>::
31+
The ref format to migrate the ref store to. Can be one of:
32+
+
33+
include::ref-storage-format.txt[]
34+
35+
--dry-run::
36+
Perform the migration, but do not modify the repository. The migrated
37+
refs will be written into a separate directory that can be inspected
38+
separately. The name of the directory will be reported on stdout. This
39+
can be used to double check that the migration works as expected before
40+
performing the actual migration.
41+
42+
KNOWN LIMITATIONS
43+
-----------------
44+
45+
The ref format migration has several known limitations in its current form:
46+
47+
* It is not possible to migrate repositories that have reflogs.
48+
49+
* It is not possible to migrate repositories that have worktrees.
50+
51+
* There is no way to block concurrent writes to the repository during an
52+
ongoing migration. Concurrent writes can lead to an inconsistent migrated
53+
state. Users are expected to block writes on a higher level. If your
54+
repository is registered for scheduled maintenance, it is recommended to
55+
unregister it first with git-maintenance(1).
56+
57+
These limitations may eventually be lifted.
58+
59+
GIT
60+
---
61+
Part of the linkgit:git[1] suite

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1283,6 +1283,7 @@ BUILTIN_OBJS += builtin/read-tree.o
12831283
BUILTIN_OBJS += builtin/rebase.o
12841284
BUILTIN_OBJS += builtin/receive-pack.o
12851285
BUILTIN_OBJS += builtin/reflog.o
1286+
BUILTIN_OBJS += builtin/refs.o
12861287
BUILTIN_OBJS += builtin/remote-ext.o
12871288
BUILTIN_OBJS += builtin/remote-fd.o
12881289
BUILTIN_OBJS += builtin/remote.o

builtin.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix);
207207
int cmd_rebase__interactive(int argc, const char **argv, const char *prefix);
208208
int cmd_receive_pack(int argc, const char **argv, const char *prefix);
209209
int cmd_reflog(int argc, const char **argv, const char *prefix);
210+
int cmd_refs(int argc, const char **argv, const char *prefix);
210211
int cmd_remote(int argc, const char **argv, const char *prefix);
211212
int cmd_remote_ext(int argc, const char **argv, const char *prefix);
212213
int cmd_remote_fd(int argc, const char **argv, const char *prefix);

builtin/refs.c

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#include "builtin.h"
2+
#include "parse-options.h"
3+
#include "refs.h"
4+
#include "repository.h"
5+
#include "strbuf.h"
6+
7+
#define REFS_MIGRATE_USAGE \
8+
N_("git refs migrate --ref-format=<format> [--dry-run]")
9+
10+
static int cmd_refs_migrate(int argc, const char **argv, const char *prefix)
11+
{
12+
const char * const migrate_usage[] = {
13+
REFS_MIGRATE_USAGE,
14+
NULL,
15+
};
16+
const char *format_str = NULL;
17+
enum ref_storage_format format;
18+
unsigned int flags = 0;
19+
struct option options[] = {
20+
OPT_STRING_F(0, "ref-format", &format_str, N_("format"),
21+
N_("specify the reference format to convert to"),
22+
PARSE_OPT_NONEG),
23+
OPT_BIT(0, "dry-run", &flags,
24+
N_("perform a non-destructive dry-run"),
25+
REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN),
26+
OPT_END(),
27+
};
28+
struct strbuf errbuf = STRBUF_INIT;
29+
int err;
30+
31+
argc = parse_options(argc, argv, prefix, options, migrate_usage, 0);
32+
if (argc)
33+
usage(_("too many arguments"));
34+
if (!format_str)
35+
usage(_("missing --ref-format=<format>"));
36+
37+
format = ref_storage_format_by_name(format_str);
38+
if (format == REF_STORAGE_FORMAT_UNKNOWN) {
39+
err = error(_("unknown ref storage format '%s'"), format_str);
40+
goto out;
41+
}
42+
43+
if (the_repository->ref_storage_format == format) {
44+
err = error(_("repository already uses '%s' format"),
45+
ref_storage_format_to_name(format));
46+
goto out;
47+
}
48+
49+
if (repo_migrate_ref_storage_format(the_repository, format, flags, &errbuf) < 0) {
50+
err = error("%s", errbuf.buf);
51+
goto out;
52+
}
53+
54+
err = 0;
55+
56+
out:
57+
strbuf_release(&errbuf);
58+
return err;
59+
}
60+
61+
int cmd_refs(int argc, const char **argv, const char *prefix)
62+
{
63+
const char * const refs_usage[] = {
64+
REFS_MIGRATE_USAGE,
65+
NULL,
66+
};
67+
parse_opt_subcommand_fn *fn = NULL;
68+
struct option opts[] = {
69+
OPT_SUBCOMMAND("migrate", &fn, cmd_refs_migrate),
70+
OPT_END(),
71+
};
72+
73+
argc = parse_options(argc, argv, prefix, opts, refs_usage, 0);
74+
return fn(argc, argv, prefix);
75+
}

command-list.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ git-read-tree plumbingmanipulators
157157
git-rebase mainporcelain history
158158
git-receive-pack synchelpers
159159
git-reflog ancillarymanipulators complete
160+
git-refs ancillarymanipulators complete
160161
git-remote ancillarymanipulators complete
161162
git-repack ancillarymanipulators complete
162163
git-replace ancillarymanipulators complete

git.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,7 @@ static struct cmd_struct commands[] = {
594594
{ "rebase", cmd_rebase, RUN_SETUP | NEED_WORK_TREE },
595595
{ "receive-pack", cmd_receive_pack },
596596
{ "reflog", cmd_reflog, RUN_SETUP },
597+
{ "refs", cmd_refs, RUN_SETUP },
597598
{ "remote", cmd_remote, RUN_SETUP },
598599
{ "remote-ext", cmd_remote_ext, NO_PARSEOPT },
599600
{ "remote-fd", cmd_remote_fd, NO_PARSEOPT },

0 commit comments

Comments
 (0)