Skip to content

Commit b0d7a56

Browse files
committed
Merge branch 'lo/repo-info' into seen
A new subcommand "git repo" gives users a way to grab various repository characteristics. * lo/repo-info: repo: add the --format flag repo: add field layout.shallow repo: add field layout.bare repo: add the field references.format repo: declare the repo command
2 parents 08281a2 + 3496ff7 commit b0d7a56

File tree

11 files changed

+306
-0
lines changed

11 files changed

+306
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@
139139
/git-repack
140140
/git-replace
141141
/git-replay
142+
/git-repo
142143
/git-request-pull
143144
/git-rerere
144145
/git-reset

Documentation/git-repo.adoc

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
git-repo(1)
2+
===========
3+
4+
NAME
5+
----
6+
git-repo - Retrieve information about a repository
7+
8+
SYNOPSIS
9+
--------
10+
[synopsis]
11+
git repo info [<key>...]
12+
13+
DESCRIPTION
14+
-----------
15+
This command retrieve repository level information.
16+
17+
THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE.
18+
19+
COMMANDS
20+
--------
21+
info [--format=<format>] [<key>...]::
22+
Retrieve metadata-related information about the current repository. Only
23+
the requested data will be returned based on their keys (see "INFO KEYS"
24+
section below).
25+
+
26+
The output format can be chosen through the flag `--format`. Two formats are
27+
supported:
28+
+
29+
* `keyvalue`: output key-value pairs one per line using the `=` character as
30+
the delimiter between the key and the value. This is the default.
31+
32+
* `null`: similar to `keyvalue`, but using a newline character as the delimiter
33+
between the key and the value and using a null character after each value.
34+
This format is better suited for being parsed by another applications than
35+
`keyvalue`.
36+
37+
INFO KEYS
38+
---------
39+
40+
The set of data that `git repo` can return is grouped into the following
41+
categories:
42+
43+
`references`::
44+
Reference-related data:
45+
* `format`: the reference storage format
46+
47+
`layout`::
48+
Information about the how the current repository is represented:
49+
* `bare`: `true` if this is a bare repository, otherwise `false`.
50+
* `shallow`: `true` if this is a shallow repository, otherwise `false`.
51+
52+
SEE ALSO
53+
--------
54+
linkgit:git-rev-parse[1]
55+
56+
GIT
57+
---
58+
Part of the linkgit:git[1] suite

Documentation/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ manpages = {
116116
'git-repack.adoc' : 1,
117117
'git-replace.adoc' : 1,
118118
'git-replay.adoc' : 1,
119+
'git-repo.adoc' : 1,
119120
'git-request-pull.adoc' : 1,
120121
'git-rerere.adoc' : 1,
121122
'git-reset.adoc' : 1,

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1306,6 +1306,7 @@ BUILTIN_OBJS += builtin/remote.o
13061306
BUILTIN_OBJS += builtin/repack.o
13071307
BUILTIN_OBJS += builtin/replace.o
13081308
BUILTIN_OBJS += builtin/replay.o
1309+
BUILTIN_OBJS += builtin/repo.o
13091310
BUILTIN_OBJS += builtin/rerere.o
13101311
BUILTIN_OBJS += builtin/reset.o
13111312
BUILTIN_OBJS += builtin/rev-list.o

builtin.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ int cmd_remote_ext(int argc, const char **argv, const char *prefix, struct repos
216216
int cmd_remote_fd(int argc, const char **argv, const char *prefix, struct repository *repo);
217217
int cmd_repack(int argc, const char **argv, const char *prefix, struct repository *repo);
218218
int cmd_replay(int argc, const char **argv, const char *prefix, struct repository *repo);
219+
int cmd_repo(int argc, const char **argv, const char *prefix, struct repository *repo);
219220
int cmd_rerere(int argc, const char **argv, const char *prefix, struct repository *repo);
220221
int cmd_reset(int argc, const char **argv, const char *prefix, struct repository *repo);
221222
int cmd_restore(int argc, const char **argv, const char *prefix, struct repository *repo);

builtin/repo.c

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
#define USE_THE_REPOSITORY_VARIABLE
2+
3+
#include "builtin.h"
4+
#include "parse-options.h"
5+
#include "refs.h"
6+
#include "environment.h"
7+
#include "shallow.h"
8+
9+
typedef const char *get_value_fn(struct repository *repo);
10+
11+
enum output_format {
12+
FORMAT_KEYVALUE,
13+
FORMAT_NULL_TERMINATED,
14+
};
15+
16+
struct field {
17+
const char *key;
18+
get_value_fn *add_field_callback;
19+
};
20+
21+
static const char *get_layout_bare(struct repository *repo UNUSED)
22+
{
23+
return is_bare_repository() ? "true" : "false";
24+
}
25+
26+
static const char *get_layout_shallow(struct repository *repo)
27+
{
28+
return is_repository_shallow(repo) ? "true" : "false";
29+
}
30+
31+
static const char *get_references_format(struct repository *repo)
32+
{
33+
return ref_storage_format_to_name(repo->ref_storage_format);
34+
}
35+
36+
/* repo_info_fields keys should be in lexicographical order */
37+
static const struct field repo_info_fields[] = {
38+
{ "layout.bare", get_layout_bare },
39+
{ "layout.shallow", get_layout_shallow },
40+
{ "references.format", get_references_format },
41+
};
42+
43+
static int repo_info_fields_cmp(const void *va, const void *vb)
44+
{
45+
const struct field *a = va;
46+
const struct field *b = vb;
47+
48+
return strcmp(a->key, b->key);
49+
}
50+
51+
static get_value_fn *get_value_callback(const char *key)
52+
{
53+
const struct field search_key = { key, NULL };
54+
const struct field *found = bsearch(&search_key, repo_info_fields,
55+
ARRAY_SIZE(repo_info_fields),
56+
sizeof(struct field),
57+
repo_info_fields_cmp);
58+
return found ? found->add_field_callback : NULL;
59+
}
60+
61+
static int qsort_strcmp(const void *va, const void *vb)
62+
{
63+
const char *a = *(const char **)va;
64+
const char *b = *(const char **)vb;
65+
66+
return strcmp(a, b);
67+
}
68+
69+
static int print_fields(int argc, const char **argv,
70+
struct repository *repo,
71+
enum output_format format)
72+
{
73+
const char *last = "";
74+
char kv_sep;
75+
char field_sep;
76+
77+
switch (format) {
78+
case FORMAT_KEYVALUE:
79+
kv_sep = '=';
80+
field_sep = '\n';
81+
break;
82+
case FORMAT_NULL_TERMINATED:
83+
kv_sep = '\n';
84+
field_sep = '\0';
85+
break;
86+
}
87+
88+
QSORT(argv, argc, qsort_strcmp);
89+
90+
for (int i = 0; i < argc; i++) {
91+
get_value_fn *callback;
92+
const char *key = argv[i];
93+
const char *value;
94+
95+
if (!strcmp(key, last))
96+
continue;
97+
98+
callback = get_value_callback(key);
99+
100+
if (!callback)
101+
return error("key %s not found", key);
102+
103+
value = callback(repo);
104+
printf("%s%c%s%c", key, kv_sep, value, field_sep);
105+
last = key;
106+
}
107+
108+
return 0;
109+
}
110+
111+
static int repo_info(int argc, const char **argv, const char *prefix,
112+
struct repository *repo)
113+
{
114+
const char *format_str = "keyvalue";
115+
enum output_format format;
116+
const char *const repo_info_usage[] = {
117+
"git repo info [<key>...]",
118+
NULL
119+
};
120+
struct option options[] = {
121+
OPT_STRING(0, "format", &format_str, N_("format"),
122+
N_("output format")),
123+
OPT_END()
124+
};
125+
126+
argc = parse_options(argc, argv, prefix, options, repo_info_usage, 0);
127+
128+
if (!strcmp(format_str, "keyvalue"))
129+
format = FORMAT_KEYVALUE;
130+
else if (!strcmp(format_str, "null"))
131+
format = FORMAT_NULL_TERMINATED;
132+
else
133+
die("invalid format %s", format_str);
134+
135+
return print_fields(argc, argv, repo, format);
136+
}
137+
138+
int cmd_repo(int argc, const char **argv, const char *prefix,
139+
struct repository *repo)
140+
{
141+
parse_opt_subcommand_fn *fn = NULL;
142+
const char *const repo_usage[] = {
143+
"git repo info [<key>...]",
144+
NULL
145+
};
146+
struct option options[] = {
147+
OPT_SUBCOMMAND("info", &fn, repo_info),
148+
OPT_END()
149+
};
150+
151+
argc = parse_options(argc, argv, prefix, options, repo_usage, 0);
152+
153+
return fn(argc, argv, prefix, repo);
154+
}

command-list.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ git-remote ancillarymanipulators complete
164164
git-repack ancillarymanipulators complete
165165
git-replace ancillarymanipulators complete
166166
git-replay plumbingmanipulators
167+
git-repo plumbinginterrogators
167168
git-request-pull foreignscminterface complete
168169
git-rerere ancillaryinterrogators
169170
git-reset mainporcelain history

git.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,7 @@ static struct cmd_struct commands[] = {
611611
{ "repack", cmd_repack, RUN_SETUP },
612612
{ "replace", cmd_replace, RUN_SETUP },
613613
{ "replay", cmd_replay, RUN_SETUP },
614+
{ "repo", cmd_repo, RUN_SETUP },
614615
{ "rerere", cmd_rerere, RUN_SETUP },
615616
{ "reset", cmd_reset, RUN_SETUP },
616617
{ "restore", cmd_restore, RUN_SETUP | NEED_WORK_TREE },

meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,7 @@ builtin_sources = [
645645
'builtin/repack.c',
646646
'builtin/replace.c',
647647
'builtin/replay.c',
648+
'builtin/repo.c',
648649
'builtin/rerere.c',
649650
'builtin/reset.c',
650651
'builtin/rev-list.c',

t/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ integration_tests = [
231231
't1700-split-index.sh',
232232
't1701-racy-split-index.sh',
233233
't1800-hook.sh',
234+
't1900-repo.sh',
234235
't2000-conflict-when-checking-files-out.sh',
235236
't2002-checkout-cache-u.sh',
236237
't2003-checkout-cache-mkdir.sh',

0 commit comments

Comments
 (0)