2 * GIT - The information manager from hell
4 * Copyright (C) Linus Torvalds, 2005
10 #include "object-name.h"
11 #include "object-store-ll.h"
15 #include "parse-options.h"
18 static const char * const ls_tree_usage
[] = {
19 N_("git ls-tree [<options>] <tree-ish> [<path>...]"),
23 static void expand_objectsize(struct strbuf
*line
, const struct object_id
*oid
,
24 const enum object_type type
, unsigned int padded
)
26 if (type
== OBJ_BLOB
) {
28 if (oid_object_info(the_repository
, oid
, &size
) < 0)
29 die(_("could not get object info about '%s'"),
32 strbuf_addf(line
, "%7"PRIuMAX
, (uintmax_t)size
);
34 strbuf_addf(line
, "%"PRIuMAX
, (uintmax_t)size
);
36 strbuf_addf(line
, "%7s", "-");
38 strbuf_addstr(line
, "-");
42 struct ls_tree_options
{
43 unsigned null_termination
:1;
45 enum ls_tree_path_options
{
46 LS_RECURSIVE
= 1 << 0,
47 LS_TREE_ONLY
= 1 << 1,
48 LS_SHOW_TREES
= 1 << 2,
50 struct pathspec pathspec
;
55 static int show_recursive(struct ls_tree_options
*options
, const char *base
,
56 size_t baselen
, const char *pathname
)
60 if (options
->ls_options
& LS_RECURSIVE
)
63 if (!options
->pathspec
.nr
)
66 for (i
= 0; i
< options
->pathspec
.nr
; i
++) {
67 const char *spec
= options
->pathspec
.items
[i
].match
;
70 if (strncmp(base
, spec
, baselen
))
72 len
= strlen(pathname
);
74 speclen
= strlen(spec
);
77 if (spec
[len
] && spec
[len
] != '/')
79 if (memcmp(pathname
, spec
, len
))
86 static int show_tree_fmt(const struct object_id
*oid
, struct strbuf
*base
,
87 const char *pathname
, unsigned mode
, void *context
)
89 struct ls_tree_options
*options
= context
;
91 struct strbuf sb
= STRBUF_INIT
;
92 enum object_type type
= object_type(mode
);
93 const char *format
= options
->format
;
95 if (type
== OBJ_TREE
&& show_recursive(options
, base
->buf
, base
->len
, pathname
))
96 recurse
= READ_TREE_RECURSIVE
;
97 if (type
== OBJ_TREE
&& recurse
&& !(options
->ls_options
& LS_SHOW_TREES
))
99 if (type
== OBJ_BLOB
&& (options
->ls_options
& LS_TREE_ONLY
))
102 while (strbuf_expand_step(&sb
, &format
)) {
106 if (skip_prefix(format
, "%", &format
))
107 strbuf_addch(&sb
, '%');
108 else if ((len
= strbuf_expand_literal(&sb
, format
)))
110 else if (*format
!= '(')
111 die(_("bad ls-tree format: element '%s' "
112 "does not start with '('"), format
);
113 else if (!(end
= strchr(format
+ 1, ')')))
114 die(_("bad ls-tree format: element '%s' "
115 "does not end in ')'"), format
);
116 else if (skip_prefix(format
, "(objectmode)", &format
))
117 strbuf_addf(&sb
, "%06o", mode
);
118 else if (skip_prefix(format
, "(objecttype)", &format
))
119 strbuf_addstr(&sb
, type_name(type
));
120 else if (skip_prefix(format
, "(objectsize:padded)", &format
))
121 expand_objectsize(&sb
, oid
, type
, 1);
122 else if (skip_prefix(format
, "(objectsize)", &format
))
123 expand_objectsize(&sb
, oid
, type
, 0);
124 else if (skip_prefix(format
, "(objectname)", &format
))
125 strbuf_add_unique_abbrev(&sb
, oid
, options
->abbrev
);
126 else if (skip_prefix(format
, "(path)", &format
)) {
128 const char *prefix
= options
->prefix
;
129 struct strbuf sbuf
= STRBUF_INIT
;
130 size_t baselen
= base
->len
;
132 strbuf_addstr(base
, pathname
);
133 name
= relative_path(base
->buf
, prefix
, &sbuf
);
134 quote_c_style(name
, &sb
, NULL
, 0);
135 strbuf_setlen(base
, baselen
);
136 strbuf_release(&sbuf
);
138 die(_("bad ls-tree format: %%%.*s"),
139 (int)(end
- format
+ 1), format
);
141 strbuf_addch(&sb
, options
->null_termination
? '\0' : '\n');
142 fwrite(sb
.buf
, sb
.len
, 1, stdout
);
147 static int show_tree_common(struct ls_tree_options
*options
, int *recurse
,
148 struct strbuf
*base
, const char *pathname
,
149 enum object_type type
)
154 if (type
== OBJ_BLOB
) {
155 if (options
->ls_options
& LS_TREE_ONLY
)
157 } else if (type
== OBJ_TREE
&&
158 show_recursive(options
, base
->buf
, base
->len
, pathname
)) {
159 *recurse
= READ_TREE_RECURSIVE
;
160 if (!(options
->ls_options
& LS_SHOW_TREES
))
167 static void show_tree_common_default_long(struct ls_tree_options
*options
,
169 const char *pathname
,
170 const size_t baselen
)
172 const char *prefix
= options
->prefix
;
174 strbuf_addstr(base
, pathname
);
176 if (options
->null_termination
) {
177 struct strbuf sb
= STRBUF_INIT
;
178 const char *name
= relative_path(base
->buf
, prefix
, &sb
);
185 write_name_quoted_relative(base
->buf
, prefix
, stdout
, '\n');
188 strbuf_setlen(base
, baselen
);
191 static int show_tree_default(const struct object_id
*oid
, struct strbuf
*base
,
192 const char *pathname
, unsigned mode
,
195 struct ls_tree_options
*options
= context
;
198 enum object_type type
= object_type(mode
);
200 early
= show_tree_common(options
, &recurse
, base
, pathname
, type
);
204 printf("%06o %s %s\t", mode
, type_name(object_type(mode
)),
205 repo_find_unique_abbrev(the_repository
, oid
, options
->abbrev
));
206 show_tree_common_default_long(options
, base
, pathname
, base
->len
);
210 static int show_tree_long(const struct object_id
*oid
, struct strbuf
*base
,
211 const char *pathname
, unsigned mode
,
214 struct ls_tree_options
*options
= context
;
218 enum object_type type
= object_type(mode
);
220 early
= show_tree_common(options
, &recurse
, base
, pathname
, type
);
224 if (type
== OBJ_BLOB
) {
226 if (oid_object_info(the_repository
, oid
, &size
) == OBJ_BAD
)
227 xsnprintf(size_text
, sizeof(size_text
), "BAD");
229 xsnprintf(size_text
, sizeof(size_text
),
230 "%" PRIuMAX
, (uintmax_t)size
);
232 xsnprintf(size_text
, sizeof(size_text
), "-");
235 printf("%06o %s %s %7s\t", mode
, type_name(type
),
236 repo_find_unique_abbrev(the_repository
, oid
, options
->abbrev
),
238 show_tree_common_default_long(options
, base
, pathname
, base
->len
);
242 static int show_tree_name_only(const struct object_id
*oid UNUSED
,
244 const char *pathname
, unsigned mode
,
247 struct ls_tree_options
*options
= context
;
250 const size_t baselen
= base
->len
;
251 enum object_type type
= object_type(mode
);
254 early
= show_tree_common(options
, &recurse
, base
, pathname
, type
);
258 prefix
= options
->prefix
;
259 strbuf_addstr(base
, pathname
);
260 if (options
->null_termination
) {
261 struct strbuf sb
= STRBUF_INIT
;
262 const char *name
= relative_path(base
->buf
, prefix
, &sb
);
269 write_name_quoted_relative(base
->buf
, prefix
, stdout
, '\n');
271 strbuf_setlen(base
, baselen
);
275 static int show_tree_object(const struct object_id
*oid
, struct strbuf
*base
,
276 const char *pathname
, unsigned mode
,
279 struct ls_tree_options
*options
= context
;
282 enum object_type type
= object_type(mode
);
285 early
= show_tree_common(options
, &recurse
, base
, pathname
, type
);
289 str
= repo_find_unique_abbrev(the_repository
, oid
, options
->abbrev
);
290 if (options
->null_termination
) {
299 enum ls_tree_cmdmode
{
307 struct ls_tree_cmdmode_to_fmt
{
308 enum ls_tree_cmdmode mode
;
309 const char *const fmt
;
313 static struct ls_tree_cmdmode_to_fmt ls_tree_cmdmode_format
[] = {
315 .mode
= MODE_DEFAULT
,
316 .fmt
= "%(objectmode) %(objecttype) %(objectname)%x09%(path)",
317 .fn
= show_tree_default
,
321 .fmt
= "%(objectmode) %(objecttype) %(objectname) %(objectsize:padded)%x09%(path)",
322 .fn
= show_tree_long
,
325 .mode
= MODE_NAME_ONLY
, /* And MODE_NAME_STATUS */
327 .fn
= show_tree_name_only
,
330 .mode
= MODE_OBJECT_ONLY
,
331 .fmt
= "%(objectname)",
332 .fn
= show_tree_object
336 .fn
= show_tree_default
,
340 int cmd_ls_tree(int argc
, const char **argv
, const char *prefix
)
342 struct object_id oid
;
344 int i
, full_tree
= 0;
345 int full_name
= !prefix
|| !*prefix
;
346 read_tree_fn_t fn
= NULL
;
347 enum ls_tree_cmdmode cmdmode
= MODE_DEFAULT
;
348 int null_termination
= 0;
349 struct ls_tree_options options
= { 0 };
350 const struct option ls_tree_options
[] = {
351 OPT_BIT('d', NULL
, &options
.ls_options
, N_("only show trees"),
353 OPT_BIT('r', NULL
, &options
.ls_options
, N_("recurse into subtrees"),
355 OPT_BIT('t', NULL
, &options
.ls_options
, N_("show trees when recursing"),
357 OPT_BOOL('z', NULL
, &null_termination
,
358 N_("terminate entries with NUL byte")),
359 OPT_CMDMODE('l', "long", &cmdmode
, N_("include object size"),
361 OPT_CMDMODE(0, "name-only", &cmdmode
, N_("list only filenames"),
363 OPT_CMDMODE(0, "name-status", &cmdmode
, N_("list only filenames"),
365 OPT_CMDMODE(0, "object-only", &cmdmode
, N_("list only objects"),
367 OPT_BOOL(0, "full-name", &full_name
, N_("use full path names")),
368 OPT_BOOL(0, "full-tree", &full_tree
,
369 N_("list entire tree; not just current directory "
370 "(implies --full-name)")),
371 OPT_STRING_F(0, "format", &options
.format
, N_("format"),
372 N_("format to use for the output"),
374 OPT__ABBREV(&options
.abbrev
),
377 struct ls_tree_cmdmode_to_fmt
*m2f
= ls_tree_cmdmode_format
;
380 git_config(git_default_config
, NULL
);
382 argc
= parse_options(argc
, argv
, prefix
, ls_tree_options
,
384 options
.null_termination
= null_termination
;
388 options
.prefix
= full_name
? NULL
: prefix
;
391 * We wanted to detect conflicts between --name-only and
392 * --name-status, but once we're done with that subsequent
393 * code should only need to check the primary name.
395 if (cmdmode
== MODE_NAME_STATUS
)
396 cmdmode
= MODE_NAME_ONLY
;
398 /* -d -r should imply -t, but -d by itself should not have to. */
399 if ( (LS_TREE_ONLY
|LS_RECURSIVE
) ==
400 ((LS_TREE_ONLY
|LS_RECURSIVE
) & options
.ls_options
))
401 options
.ls_options
|= LS_SHOW_TREES
;
403 if (options
.format
&& cmdmode
)
405 _("--format can't be combined with other format-altering options"),
406 ls_tree_usage
, ls_tree_options
);
408 usage_with_options(ls_tree_usage
, ls_tree_options
);
409 if (repo_get_oid(the_repository
, argv
[0], &oid
))
410 die("Not a valid object name %s", argv
[0]);
413 * show_recursive() rolls its own matching code and is
414 * generally ignorant of 'struct pathspec'. The magic mask
415 * cannot be lifted until it is converted to use
416 * match_pathspec() or tree_entry_interesting()
418 parse_pathspec(&options
.pathspec
, PATHSPEC_ALL_MAGIC
&
419 ~(PATHSPEC_FROMTOP
| PATHSPEC_LITERAL
),
422 for (i
= 0; i
< options
.pathspec
.nr
; i
++)
423 options
.pathspec
.items
[i
].nowildcard_len
= options
.pathspec
.items
[i
].len
;
424 options
.pathspec
.has_wildcard
= 0;
425 tree
= parse_tree_indirect(&oid
);
427 die("not a tree object");
429 * The generic show_tree_fmt() is slower than show_tree(), so
430 * take the fast path if possible.
434 fn
= options
.format
? show_tree_fmt
: show_tree_default
;
435 } else if (options
.format
&& !strcmp(options
.format
, m2f
->fmt
)) {
438 } else if (!options
.format
&& cmdmode
== m2f
->mode
) {
447 ret
= !!read_tree(the_repository
, tree
, &options
.pathspec
, fn
, &options
);
448 clear_pathspec(&options
.pathspec
);