t/helper: allow chmtime to print verbosely without modifying mtime
[alt-git.git] / builtin / ls-tree.c
blob8cc8c995df9399cd84465060965d065d33cd5d3b
1 /*
2 * GIT - The information manager from hell
4 * Copyright (C) Linus Torvalds, 2005
5 */
6 #include "cache.h"
7 #include "config.h"
8 #include "object-store.h"
9 #include "blob.h"
10 #include "tree.h"
11 #include "commit.h"
12 #include "quote.h"
13 #include "builtin.h"
14 #include "parse-options.h"
15 #include "pathspec.h"
17 static const char * const ls_tree_usage[] = {
18 N_("git ls-tree [<options>] <tree-ish> [<path>...]"),
19 NULL
22 static void expand_objectsize(struct strbuf *line, const struct object_id *oid,
23 const enum object_type type, unsigned int padded)
25 if (type == OBJ_BLOB) {
26 unsigned long size;
27 if (oid_object_info(the_repository, oid, &size) < 0)
28 die(_("could not get object info about '%s'"),
29 oid_to_hex(oid));
30 if (padded)
31 strbuf_addf(line, "%7"PRIuMAX, (uintmax_t)size);
32 else
33 strbuf_addf(line, "%"PRIuMAX, (uintmax_t)size);
34 } else if (padded) {
35 strbuf_addf(line, "%7s", "-");
36 } else {
37 strbuf_addstr(line, "-");
41 struct ls_tree_options {
42 unsigned null_termination:1;
43 int abbrev;
44 enum ls_tree_path_options {
45 LS_RECURSIVE = 1 << 0,
46 LS_TREE_ONLY = 1 << 1,
47 LS_SHOW_TREES = 1 << 2,
48 } ls_options;
49 struct pathspec pathspec;
50 int chomp_prefix;
51 const char *ls_tree_prefix;
52 const char *format;
55 struct show_tree_data {
56 struct ls_tree_options *options;
57 unsigned mode;
58 enum object_type type;
59 const struct object_id *oid;
60 const char *pathname;
61 struct strbuf *base;
64 static size_t expand_show_tree(struct strbuf *sb, const char *start,
65 void *context)
67 struct show_tree_data *data = context;
68 struct ls_tree_options *options = data->options;
69 const char *end;
70 const char *p;
71 unsigned int errlen;
72 size_t len = strbuf_expand_literal_cb(sb, start, NULL);
74 if (len)
75 return len;
76 if (*start != '(')
77 die(_("bad ls-tree format: element '%s' does not start with '('"), start);
79 end = strchr(start + 1, ')');
80 if (!end)
81 die(_("bad ls-tree format: element '%s' does not end in ')'"), start);
83 len = end - start + 1;
84 if (skip_prefix(start, "(objectmode)", &p)) {
85 strbuf_addf(sb, "%06o", data->mode);
86 } else if (skip_prefix(start, "(objecttype)", &p)) {
87 strbuf_addstr(sb, type_name(data->type));
88 } else if (skip_prefix(start, "(objectsize:padded)", &p)) {
89 expand_objectsize(sb, data->oid, data->type, 1);
90 } else if (skip_prefix(start, "(objectsize)", &p)) {
91 expand_objectsize(sb, data->oid, data->type, 0);
92 } else if (skip_prefix(start, "(objectname)", &p)) {
93 strbuf_add_unique_abbrev(sb, data->oid, options->abbrev);
94 } else if (skip_prefix(start, "(path)", &p)) {
95 const char *name = data->base->buf;
96 const char *prefix = options->chomp_prefix ? options->ls_tree_prefix : NULL;
97 struct strbuf sbuf = STRBUF_INIT;
98 size_t baselen = data->base->len;
100 strbuf_addstr(data->base, data->pathname);
101 name = relative_path(data->base->buf, prefix, &sbuf);
102 quote_c_style(name, sb, NULL, 0);
103 strbuf_setlen(data->base, baselen);
104 strbuf_release(&sbuf);
105 } else {
106 errlen = (unsigned long)len;
107 die(_("bad ls-tree format: %%%.*s"), errlen, start);
109 return len;
112 static int show_recursive(struct ls_tree_options *options, const char *base,
113 size_t baselen, const char *pathname)
115 int i;
117 if (options->ls_options & LS_RECURSIVE)
118 return 1;
120 if (!options->pathspec.nr)
121 return 0;
123 for (i = 0; i < options->pathspec.nr; i++) {
124 const char *spec = options->pathspec.items[i].match;
125 size_t len, speclen;
127 if (strncmp(base, spec, baselen))
128 continue;
129 len = strlen(pathname);
130 spec += baselen;
131 speclen = strlen(spec);
132 if (speclen <= len)
133 continue;
134 if (spec[len] && spec[len] != '/')
135 continue;
136 if (memcmp(pathname, spec, len))
137 continue;
138 return 1;
140 return 0;
143 static int show_tree_fmt(const struct object_id *oid, struct strbuf *base,
144 const char *pathname, unsigned mode, void *context)
146 struct ls_tree_options *options = context;
147 int recurse = 0;
148 struct strbuf sb = STRBUF_INIT;
149 enum object_type type = object_type(mode);
150 struct show_tree_data cb_data = {
151 .options = options,
152 .mode = mode,
153 .type = type,
154 .oid = oid,
155 .pathname = pathname,
156 .base = base,
159 if (type == OBJ_TREE && show_recursive(options, base->buf, base->len, pathname))
160 recurse = READ_TREE_RECURSIVE;
161 if (type == OBJ_TREE && recurse && !(options->ls_options & LS_SHOW_TREES))
162 return recurse;
163 if (type == OBJ_BLOB && (options->ls_options & LS_TREE_ONLY))
164 return 0;
166 strbuf_expand(&sb, options->format, expand_show_tree, &cb_data);
167 strbuf_addch(&sb, options->null_termination ? '\0' : '\n');
168 fwrite(sb.buf, sb.len, 1, stdout);
169 strbuf_release(&sb);
170 return recurse;
173 static int show_tree_common(struct ls_tree_options *options, int *recurse,
174 struct strbuf *base, const char *pathname,
175 enum object_type type)
177 int ret = -1;
178 *recurse = 0;
180 if (type == OBJ_BLOB) {
181 if (options->ls_options & LS_TREE_ONLY)
182 ret = 0;
183 } else if (type == OBJ_TREE &&
184 show_recursive(options, base->buf, base->len, pathname)) {
185 *recurse = READ_TREE_RECURSIVE;
186 if (!(options->ls_options & LS_SHOW_TREES))
187 ret = *recurse;
190 return ret;
193 static void show_tree_common_default_long(struct ls_tree_options *options,
194 struct strbuf *base,
195 const char *pathname,
196 const size_t baselen)
198 const char *prefix = options->chomp_prefix ? options->ls_tree_prefix : NULL;
200 strbuf_addstr(base, pathname);
202 if (options->null_termination) {
203 struct strbuf sb = STRBUF_INIT;
204 const char *name = relative_path(base->buf, prefix, &sb);
206 fputs(name, stdout);
207 fputc('\0', stdout);
209 strbuf_release(&sb);
210 } else {
211 write_name_quoted_relative(base->buf, prefix, stdout, '\n');
214 strbuf_setlen(base, baselen);
217 static int show_tree_default(const struct object_id *oid, struct strbuf *base,
218 const char *pathname, unsigned mode,
219 void *context)
221 struct ls_tree_options *options = context;
222 int early;
223 int recurse;
224 enum object_type type = object_type(mode);
226 early = show_tree_common(options, &recurse, base, pathname, type);
227 if (early >= 0)
228 return early;
230 printf("%06o %s %s\t", mode, type_name(object_type(mode)),
231 find_unique_abbrev(oid, options->abbrev));
232 show_tree_common_default_long(options, base, pathname, base->len);
233 return recurse;
236 static int show_tree_long(const struct object_id *oid, struct strbuf *base,
237 const char *pathname, unsigned mode,
238 void *context)
240 struct ls_tree_options *options = context;
241 int early;
242 int recurse;
243 char size_text[24];
244 enum object_type type = object_type(mode);
246 early = show_tree_common(options, &recurse, base, pathname, type);
247 if (early >= 0)
248 return early;
250 if (type == OBJ_BLOB) {
251 unsigned long size;
252 if (oid_object_info(the_repository, oid, &size) == OBJ_BAD)
253 xsnprintf(size_text, sizeof(size_text), "BAD");
254 else
255 xsnprintf(size_text, sizeof(size_text),
256 "%" PRIuMAX, (uintmax_t)size);
257 } else {
258 xsnprintf(size_text, sizeof(size_text), "-");
261 printf("%06o %s %s %7s\t", mode, type_name(type),
262 find_unique_abbrev(oid, options->abbrev), size_text);
263 show_tree_common_default_long(options, base, pathname, base->len);
264 return recurse;
267 static int show_tree_name_only(const struct object_id *oid, struct strbuf *base,
268 const char *pathname, unsigned mode,
269 void *context)
271 struct ls_tree_options *options = context;
272 int early;
273 int recurse;
274 const size_t baselen = base->len;
275 enum object_type type = object_type(mode);
276 const char *prefix;
278 early = show_tree_common(options, &recurse, base, pathname, type);
279 if (early >= 0)
280 return early;
282 prefix = options->chomp_prefix ? options->ls_tree_prefix : NULL;
283 strbuf_addstr(base, pathname);
284 if (options->null_termination) {
285 struct strbuf sb = STRBUF_INIT;
286 const char *name = relative_path(base->buf, prefix, &sb);
288 fputs(name, stdout);
289 fputc('\0', stdout);
291 strbuf_release(&sb);
292 } else {
293 write_name_quoted_relative(base->buf, prefix, stdout, '\n');
295 strbuf_setlen(base, baselen);
296 return recurse;
299 static int show_tree_object(const struct object_id *oid, struct strbuf *base,
300 const char *pathname, unsigned mode,
301 void *context)
303 struct ls_tree_options *options = context;
304 int early;
305 int recurse;
306 enum object_type type = object_type(mode);
307 const char *str;
309 early = show_tree_common(options, &recurse, base, pathname, type);
310 if (early >= 0)
311 return early;
313 str = find_unique_abbrev(oid, options->abbrev);
314 if (options->null_termination) {
315 fputs(str, stdout);
316 fputc('\0', stdout);
317 } else {
318 puts(str);
320 return recurse;
323 enum ls_tree_cmdmode {
324 MODE_DEFAULT = 0,
325 MODE_LONG,
326 MODE_NAME_ONLY,
327 MODE_NAME_STATUS,
328 MODE_OBJECT_ONLY,
331 struct ls_tree_cmdmode_to_fmt {
332 enum ls_tree_cmdmode mode;
333 const char *const fmt;
334 read_tree_fn_t fn;
337 static struct ls_tree_cmdmode_to_fmt ls_tree_cmdmode_format[] = {
339 .mode = MODE_DEFAULT,
340 .fmt = "%(objectmode) %(objecttype) %(objectname)%x09%(path)",
341 .fn = show_tree_default,
344 .mode = MODE_LONG,
345 .fmt = "%(objectmode) %(objecttype) %(objectname) %(objectsize:padded)%x09%(path)",
346 .fn = show_tree_long,
349 .mode = MODE_NAME_ONLY, /* And MODE_NAME_STATUS */
350 .fmt = "%(path)",
351 .fn = show_tree_name_only,
354 .mode = MODE_OBJECT_ONLY,
355 .fmt = "%(objectname)",
356 .fn = show_tree_object
359 /* fallback */
360 .fn = show_tree_default,
364 int cmd_ls_tree(int argc, const char **argv, const char *prefix)
366 struct object_id oid;
367 struct tree *tree;
368 int i, full_tree = 0;
369 read_tree_fn_t fn = NULL;
370 enum ls_tree_cmdmode cmdmode = MODE_DEFAULT;
371 int null_termination = 0;
372 struct ls_tree_options options = { 0 };
373 const struct option ls_tree_options[] = {
374 OPT_BIT('d', NULL, &options.ls_options, N_("only show trees"),
375 LS_TREE_ONLY),
376 OPT_BIT('r', NULL, &options.ls_options, N_("recurse into subtrees"),
377 LS_RECURSIVE),
378 OPT_BIT('t', NULL, &options.ls_options, N_("show trees when recursing"),
379 LS_SHOW_TREES),
380 OPT_BOOL('z', NULL, &null_termination,
381 N_("terminate entries with NUL byte")),
382 OPT_CMDMODE('l', "long", &cmdmode, N_("include object size"),
383 MODE_LONG),
384 OPT_CMDMODE(0, "name-only", &cmdmode, N_("list only filenames"),
385 MODE_NAME_ONLY),
386 OPT_CMDMODE(0, "name-status", &cmdmode, N_("list only filenames"),
387 MODE_NAME_STATUS),
388 OPT_CMDMODE(0, "object-only", &cmdmode, N_("list only objects"),
389 MODE_OBJECT_ONLY),
390 OPT_SET_INT(0, "full-name", &options.chomp_prefix,
391 N_("use full path names"), 0),
392 OPT_BOOL(0, "full-tree", &full_tree,
393 N_("list entire tree; not just current directory "
394 "(implies --full-name)")),
395 OPT_STRING_F(0, "format", &options.format, N_("format"),
396 N_("format to use for the output"),
397 PARSE_OPT_NONEG),
398 OPT__ABBREV(&options.abbrev),
399 OPT_END()
401 struct ls_tree_cmdmode_to_fmt *m2f = ls_tree_cmdmode_format;
402 int ret;
404 git_config(git_default_config, NULL);
405 options.ls_tree_prefix = prefix;
406 if (prefix)
407 options.chomp_prefix = strlen(prefix);
409 argc = parse_options(argc, argv, prefix, ls_tree_options,
410 ls_tree_usage, 0);
411 options.null_termination = null_termination;
413 if (full_tree) {
414 options.ls_tree_prefix = prefix = NULL;
415 options.chomp_prefix = 0;
418 * We wanted to detect conflicts between --name-only and
419 * --name-status, but once we're done with that subsequent
420 * code should only need to check the primary name.
422 if (cmdmode == MODE_NAME_STATUS)
423 cmdmode = MODE_NAME_ONLY;
425 /* -d -r should imply -t, but -d by itself should not have to. */
426 if ( (LS_TREE_ONLY|LS_RECURSIVE) ==
427 ((LS_TREE_ONLY|LS_RECURSIVE) & options.ls_options))
428 options.ls_options |= LS_SHOW_TREES;
430 if (options.format && cmdmode)
431 usage_msg_opt(
432 _("--format can't be combined with other format-altering options"),
433 ls_tree_usage, ls_tree_options);
434 if (argc < 1)
435 usage_with_options(ls_tree_usage, ls_tree_options);
436 if (get_oid(argv[0], &oid))
437 die("Not a valid object name %s", argv[0]);
440 * show_recursive() rolls its own matching code and is
441 * generally ignorant of 'struct pathspec'. The magic mask
442 * cannot be lifted until it is converted to use
443 * match_pathspec() or tree_entry_interesting()
445 parse_pathspec(&options.pathspec, PATHSPEC_ALL_MAGIC &
446 ~(PATHSPEC_FROMTOP | PATHSPEC_LITERAL),
447 PATHSPEC_PREFER_CWD,
448 prefix, argv + 1);
449 for (i = 0; i < options.pathspec.nr; i++)
450 options.pathspec.items[i].nowildcard_len = options.pathspec.items[i].len;
451 options.pathspec.has_wildcard = 0;
452 tree = parse_tree_indirect(&oid);
453 if (!tree)
454 die("not a tree object");
456 * The generic show_tree_fmt() is slower than show_tree(), so
457 * take the fast path if possible.
459 while (m2f) {
460 if (!m2f->fmt) {
461 fn = options.format ? show_tree_fmt : show_tree_default;
462 } else if (options.format && !strcmp(options.format, m2f->fmt)) {
463 cmdmode = m2f->mode;
464 fn = m2f->fn;
465 } else if (!options.format && cmdmode == m2f->mode) {
466 fn = m2f->fn;
467 } else {
468 m2f++;
469 continue;
471 break;
474 ret = !!read_tree(the_repository, tree, &options.pathspec, fn, &options);
475 clear_pathspec(&options.pathspec);
476 return ret;