git

Форк
0
/
check-attr.c 
204 строки · 5.1 Кб
1
#include "builtin.h"
2
#include "config.h"
3
#include "attr.h"
4
#include "environment.h"
5
#include "gettext.h"
6
#include "object-name.h"
7
#include "quote.h"
8
#include "repository.h"
9
#include "setup.h"
10
#include "parse-options.h"
11
#include "write-or-die.h"
12

13
static int all_attrs;
14
static int cached_attrs;
15
static int stdin_paths;
16
static char *source;
17
static const char * const check_attr_usage[] = {
18
N_("git check-attr [--source <tree-ish>] [-a | --all | <attr>...] [--] <pathname>..."),
19
N_("git check-attr --stdin [-z] [--source <tree-ish>] [-a | --all | <attr>...]"),
20
NULL
21
};
22

23
static int nul_term_line;
24

25
static const struct option check_attr_options[] = {
26
	OPT_BOOL('a', "all", &all_attrs, N_("report all attributes set on file")),
27
	OPT_BOOL(0,  "cached", &cached_attrs, N_("use .gitattributes only from the index")),
28
	OPT_BOOL(0 , "stdin", &stdin_paths, N_("read file names from stdin")),
29
	OPT_BOOL('z', NULL, &nul_term_line,
30
		 N_("terminate input and output records by a NUL character")),
31
	OPT_STRING(0, "source", &source, N_("<tree-ish>"), N_("which tree-ish to check attributes at")),
32
	OPT_END()
33
};
34

35
static void output_attr(struct attr_check *check, const char *file)
36
{
37
	int j;
38
	int cnt = check->nr;
39

40
	for (j = 0; j < cnt; j++) {
41
		const char *value = check->items[j].value;
42

43
		if (ATTR_TRUE(value))
44
			value = "set";
45
		else if (ATTR_FALSE(value))
46
			value = "unset";
47
		else if (ATTR_UNSET(value))
48
			value = "unspecified";
49

50
		if (nul_term_line) {
51
			printf("%s%c" /* path */
52
			       "%s%c" /* attrname */
53
			       "%s%c" /* attrvalue */,
54
			       file, 0,
55
			       git_attr_name(check->items[j].attr), 0, value, 0);
56
		} else {
57
			quote_c_style(file, NULL, stdout, 0);
58
			printf(": %s: %s\n",
59
			       git_attr_name(check->items[j].attr), value);
60
		}
61
	}
62
}
63

64
static void check_attr(const char *prefix, struct attr_check *check,
65
		       int collect_all,
66
		       const char *file)
67

68
{
69
	char *full_path =
70
		prefix_path(prefix, prefix ? strlen(prefix) : 0, file);
71

72
	if (collect_all) {
73
		git_all_attrs(the_repository->index, full_path, check);
74
	} else {
75
		git_check_attr(the_repository->index, full_path, check);
76
	}
77
	output_attr(check, file);
78

79
	free(full_path);
80
}
81

82
static void check_attr_stdin_paths(const char *prefix, struct attr_check *check,
83
				   int collect_all)
84
{
85
	struct strbuf buf = STRBUF_INIT;
86
	struct strbuf unquoted = STRBUF_INIT;
87
	strbuf_getline_fn getline_fn;
88

89
	getline_fn = nul_term_line ? strbuf_getline_nul : strbuf_getline_lf;
90
	while (getline_fn(&buf, stdin) != EOF) {
91
		if (!nul_term_line && buf.buf[0] == '"') {
92
			strbuf_reset(&unquoted);
93
			if (unquote_c_style(&unquoted, buf.buf, NULL))
94
				die("line is badly quoted");
95
			strbuf_swap(&buf, &unquoted);
96
		}
97
		check_attr(prefix, check, collect_all, buf.buf);
98
		maybe_flush_or_die(stdout, "attribute to stdout");
99
	}
100
	strbuf_release(&buf);
101
	strbuf_release(&unquoted);
102
}
103

104
static NORETURN void error_with_usage(const char *msg)
105
{
106
	error("%s", msg);
107
	usage_with_options(check_attr_usage, check_attr_options);
108
}
109

110
int cmd_check_attr(int argc, const char **argv, const char *prefix)
111
{
112
	struct attr_check *check;
113
	struct object_id initialized_oid;
114
	int cnt, i, doubledash, filei;
115

116
	if (!is_bare_repository())
117
		setup_work_tree();
118

119
	git_config(git_default_config, NULL);
120

121
	argc = parse_options(argc, argv, prefix, check_attr_options,
122
			     check_attr_usage, PARSE_OPT_KEEP_DASHDASH);
123

124
	prepare_repo_settings(the_repository);
125
	the_repository->settings.command_requires_full_index = 0;
126

127
	if (repo_read_index(the_repository) < 0) {
128
		die("invalid cache");
129
	}
130

131
	if (cached_attrs)
132
		git_attr_set_direction(GIT_ATTR_INDEX);
133

134
	doubledash = -1;
135
	for (i = 0; doubledash < 0 && i < argc; i++) {
136
		if (!strcmp(argv[i], "--"))
137
			doubledash = i;
138
	}
139

140
	/* Process --all and/or attribute arguments: */
141
	if (all_attrs) {
142
		if (doubledash >= 1)
143
			error_with_usage("Attributes and --all both specified");
144

145
		cnt = 0;
146
		filei = doubledash + 1;
147
	} else if (doubledash == 0) {
148
		error_with_usage("No attribute specified");
149
	} else if (doubledash < 0) {
150
		if (!argc)
151
			error_with_usage("No attribute specified");
152

153
		if (stdin_paths) {
154
			/* Treat all arguments as attribute names. */
155
			cnt = argc;
156
			filei = argc;
157
		} else {
158
			/* Treat exactly one argument as an attribute name. */
159
			cnt = 1;
160
			filei = 1;
161
		}
162
	} else {
163
		cnt = doubledash;
164
		filei = doubledash + 1;
165
	}
166

167
	/* Check file argument(s): */
168
	if (stdin_paths) {
169
		if (filei < argc)
170
			error_with_usage("Can't specify files with --stdin");
171
	} else {
172
		if (filei >= argc)
173
			error_with_usage("No file specified");
174
	}
175

176
	check = attr_check_alloc();
177
	if (!all_attrs) {
178
		for (i = 0; i < cnt; i++) {
179
			const struct git_attr *a = git_attr(argv[i]);
180

181
			if (!a)
182
				return error("%s: not a valid attribute name",
183
					     argv[i]);
184
			attr_check_append(check, a);
185
		}
186
	}
187

188
	if (source) {
189
		if (repo_get_oid_tree(the_repository, source, &initialized_oid))
190
			die("%s: not a valid tree-ish source", source);
191
		set_git_attr_source(source);
192
	}
193

194
	if (stdin_paths)
195
		check_attr_stdin_paths(prefix, check, all_attrs);
196
	else {
197
		for (i = filei; i < argc; i++)
198
			check_attr(prefix, check, all_attrs, argv[i]);
199
		maybe_flush_or_die(stdout, "attribute to stdout");
200
	}
201

202
	attr_check_free(check);
203
	return 0;
204
}
205

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.