2 * GIT - The information manager from hell
4 * Copyright (C) Linus Torvalds, 2005
8 #include "object-store.h"
14 #include "parse-options.h"
17 static int line_termination
= '\n';
18 #define LS_RECURSIVE 1
19 #define LS_TREE_ONLY (1 << 1)
20 #define LS_SHOW_TREES (1 << 2)
22 static int ls_options
;
23 static struct pathspec pathspec
;
24 static int chomp_prefix
;
25 static const char *ls_tree_prefix
;
26 static const char *format
;
27 struct show_tree_data
{
29 enum object_type type
;
30 const struct object_id
*oid
;
35 static const char * const ls_tree_usage
[] = {
36 N_("git ls-tree [<options>] <tree-ish> [<path>...]"),
40 static enum ls_tree_cmdmode
{
48 static void expand_objectsize(struct strbuf
*line
, const struct object_id
*oid
,
49 const enum object_type type
, unsigned int padded
)
51 if (type
== OBJ_BLOB
) {
53 if (oid_object_info(the_repository
, oid
, &size
) < 0)
54 die(_("could not get object info about '%s'"),
57 strbuf_addf(line
, "%7"PRIuMAX
, (uintmax_t)size
);
59 strbuf_addf(line
, "%"PRIuMAX
, (uintmax_t)size
);
61 strbuf_addf(line
, "%7s", "-");
63 strbuf_addstr(line
, "-");
67 static size_t expand_show_tree(struct strbuf
*sb
, const char *start
,
70 struct show_tree_data
*data
= context
;
74 size_t len
= strbuf_expand_literal_cb(sb
, start
, NULL
);
79 die(_("bad ls-tree format: element '%s' does not start with '('"), start
);
81 end
= strchr(start
+ 1, ')');
83 die(_("bad ls-tree format: element '%s' does not end in ')'"), start
);
85 len
= end
- start
+ 1;
86 if (skip_prefix(start
, "(objectmode)", &p
)) {
87 strbuf_addf(sb
, "%06o", data
->mode
);
88 } else if (skip_prefix(start
, "(objecttype)", &p
)) {
89 strbuf_addstr(sb
, type_name(data
->type
));
90 } else if (skip_prefix(start
, "(objectsize:padded)", &p
)) {
91 expand_objectsize(sb
, data
->oid
, data
->type
, 1);
92 } else if (skip_prefix(start
, "(objectsize)", &p
)) {
93 expand_objectsize(sb
, data
->oid
, data
->type
, 0);
94 } else if (skip_prefix(start
, "(objectname)", &p
)) {
95 strbuf_add_unique_abbrev(sb
, data
->oid
, abbrev
);
96 } else if (skip_prefix(start
, "(path)", &p
)) {
97 const char *name
= data
->base
->buf
;
98 const char *prefix
= chomp_prefix
? ls_tree_prefix
: NULL
;
99 struct strbuf quoted
= STRBUF_INIT
;
100 struct strbuf sbuf
= STRBUF_INIT
;
101 strbuf_addstr(data
->base
, data
->pathname
);
102 name
= relative_path(data
->base
->buf
, prefix
, &sbuf
);
103 quote_c_style(name
, "ed
, NULL
, 0);
104 strbuf_addbuf(sb
, "ed
);
105 strbuf_release(&sbuf
);
106 strbuf_release("ed
);
108 errlen
= (unsigned long)len
;
109 die(_("bad ls-tree format: %%%.*s"), errlen
, start
);
114 static int show_recursive(const char *base
, size_t baselen
, const char *pathname
)
118 if (ls_options
& LS_RECURSIVE
)
124 for (i
= 0; i
< pathspec
.nr
; i
++) {
125 const char *spec
= pathspec
.items
[i
].match
;
128 if (strncmp(base
, spec
, baselen
))
130 len
= strlen(pathname
);
132 speclen
= strlen(spec
);
135 if (spec
[len
] && spec
[len
] != '/')
137 if (memcmp(pathname
, spec
, len
))
144 static int show_tree_fmt(const struct object_id
*oid
, struct strbuf
*base
,
145 const char *pathname
, unsigned mode
, void *context UNUSED
)
149 struct strbuf sb
= STRBUF_INIT
;
150 enum object_type type
= object_type(mode
);
152 struct show_tree_data data
= {
156 .pathname
= pathname
,
160 if (type
== OBJ_TREE
&& show_recursive(base
->buf
, base
->len
, pathname
))
161 recurse
= READ_TREE_RECURSIVE
;
162 if (type
== OBJ_TREE
&& recurse
&& !(ls_options
& LS_SHOW_TREES
))
164 if (type
== OBJ_BLOB
&& (ls_options
& LS_TREE_ONLY
))
168 strbuf_expand(&sb
, format
, expand_show_tree
, &data
);
169 strbuf_addch(&sb
, line_termination
);
170 fwrite(sb
.buf
, sb
.len
, 1, stdout
);
172 strbuf_setlen(base
, baselen
);
176 static int show_tree_common(struct show_tree_data
*data
, int *recurse
,
177 const struct object_id
*oid
, struct strbuf
*base
,
178 const char *pathname
, unsigned mode
)
180 enum object_type type
= object_type(mode
);
187 data
->pathname
= pathname
;
190 if (type
== OBJ_BLOB
) {
191 if (ls_options
& LS_TREE_ONLY
)
193 } else if (type
== OBJ_TREE
&&
194 show_recursive(base
->buf
, base
->len
, pathname
)) {
195 *recurse
= READ_TREE_RECURSIVE
;
196 if (!(ls_options
& LS_SHOW_TREES
))
203 static void show_tree_common_default_long(struct strbuf
*base
,
204 const char *pathname
,
205 const size_t baselen
)
207 strbuf_addstr(base
, pathname
);
208 write_name_quoted_relative(base
->buf
,
209 chomp_prefix
? ls_tree_prefix
: NULL
, stdout
,
211 strbuf_setlen(base
, baselen
);
214 static int show_tree_default(const struct object_id
*oid
, struct strbuf
*base
,
215 const char *pathname
, unsigned mode
,
216 void *context UNUSED
)
220 struct show_tree_data data
= { 0 };
222 early
= show_tree_common(&data
, &recurse
, oid
, base
, pathname
, mode
);
226 printf("%06o %s %s\t", data
.mode
, type_name(data
.type
),
227 find_unique_abbrev(data
.oid
, abbrev
));
228 show_tree_common_default_long(base
, pathname
, data
.base
->len
);
232 static int show_tree_long(const struct object_id
*oid
, struct strbuf
*base
,
233 const char *pathname
, unsigned mode
,
234 void *context UNUSED
)
238 struct show_tree_data data
= { 0 };
241 early
= show_tree_common(&data
, &recurse
, oid
, base
, pathname
, mode
);
245 if (data
.type
== OBJ_BLOB
) {
247 if (oid_object_info(the_repository
, data
.oid
, &size
) == OBJ_BAD
)
248 xsnprintf(size_text
, sizeof(size_text
), "BAD");
250 xsnprintf(size_text
, sizeof(size_text
),
251 "%" PRIuMAX
, (uintmax_t)size
);
253 xsnprintf(size_text
, sizeof(size_text
), "-");
256 printf("%06o %s %s %7s\t", data
.mode
, type_name(data
.type
),
257 find_unique_abbrev(data
.oid
, abbrev
), size_text
);
258 show_tree_common_default_long(base
, pathname
, data
.base
->len
);
262 static int show_tree_name_only(const struct object_id
*oid
, struct strbuf
*base
,
263 const char *pathname
, unsigned mode
,
264 void *context UNUSED
)
268 const size_t baselen
= base
->len
;
269 struct show_tree_data data
= { 0 };
271 early
= show_tree_common(&data
, &recurse
, oid
, base
, pathname
, mode
);
275 strbuf_addstr(base
, pathname
);
276 write_name_quoted_relative(base
->buf
,
277 chomp_prefix
? ls_tree_prefix
: NULL
,
278 stdout
, line_termination
);
279 strbuf_setlen(base
, baselen
);
283 static int show_tree_object(const struct object_id
*oid
, struct strbuf
*base
,
284 const char *pathname
, unsigned mode
,
285 void *context UNUSED
)
289 struct show_tree_data data
= { 0 };
291 early
= show_tree_common(&data
, &recurse
, oid
, base
, pathname
, mode
);
295 printf("%s%c", find_unique_abbrev(oid
, abbrev
), line_termination
);
299 struct ls_tree_cmdmode_to_fmt
{
300 enum ls_tree_cmdmode mode
;
301 const char *const fmt
;
305 static struct ls_tree_cmdmode_to_fmt ls_tree_cmdmode_format
[] = {
307 .mode
= MODE_DEFAULT
,
308 .fmt
= "%(objectmode) %(objecttype) %(objectname)%x09%(path)",
309 .fn
= show_tree_default
,
313 .fmt
= "%(objectmode) %(objecttype) %(objectname) %(objectsize:padded)%x09%(path)",
314 .fn
= show_tree_long
,
317 .mode
= MODE_NAME_ONLY
, /* And MODE_NAME_STATUS */
319 .fn
= show_tree_name_only
,
322 .mode
= MODE_OBJECT_ONLY
,
323 .fmt
= "%(objectname)",
324 .fn
= show_tree_object
328 .fn
= show_tree_default
,
332 int cmd_ls_tree(int argc
, const char **argv
, const char *prefix
)
334 struct object_id oid
;
336 int i
, full_tree
= 0;
337 read_tree_fn_t fn
= NULL
;
338 const struct option ls_tree_options
[] = {
339 OPT_BIT('d', NULL
, &ls_options
, N_("only show trees"),
341 OPT_BIT('r', NULL
, &ls_options
, N_("recurse into subtrees"),
343 OPT_BIT('t', NULL
, &ls_options
, N_("show trees when recursing"),
345 OPT_SET_INT('z', NULL
, &line_termination
,
346 N_("terminate entries with NUL byte"), 0),
347 OPT_CMDMODE('l', "long", &cmdmode
, N_("include object size"),
349 OPT_CMDMODE(0, "name-only", &cmdmode
, N_("list only filenames"),
351 OPT_CMDMODE(0, "name-status", &cmdmode
, N_("list only filenames"),
353 OPT_CMDMODE(0, "object-only", &cmdmode
, N_("list only objects"),
355 OPT_SET_INT(0, "full-name", &chomp_prefix
,
356 N_("use full path names"), 0),
357 OPT_BOOL(0, "full-tree", &full_tree
,
358 N_("list entire tree; not just current directory "
359 "(implies --full-name)")),
360 OPT_STRING_F(0, "format", &format
, N_("format"),
361 N_("format to use for the output"),
363 OPT__ABBREV(&abbrev
),
366 struct ls_tree_cmdmode_to_fmt
*m2f
= ls_tree_cmdmode_format
;
368 git_config(git_default_config
, NULL
);
369 ls_tree_prefix
= prefix
;
371 chomp_prefix
= strlen(prefix
);
373 argc
= parse_options(argc
, argv
, prefix
, ls_tree_options
,
376 ls_tree_prefix
= prefix
= NULL
;
380 * We wanted to detect conflicts between --name-only and
381 * --name-status, but once we're done with that subsequent
382 * code should only need to check the primary name.
384 if (cmdmode
== MODE_NAME_STATUS
)
385 cmdmode
= MODE_NAME_ONLY
;
387 /* -d -r should imply -t, but -d by itself should not have to. */
388 if ( (LS_TREE_ONLY
|LS_RECURSIVE
) ==
389 ((LS_TREE_ONLY
|LS_RECURSIVE
) & ls_options
))
390 ls_options
|= LS_SHOW_TREES
;
392 if (format
&& cmdmode
)
394 _("--format can't be combined with other format-altering options"),
395 ls_tree_usage
, ls_tree_options
);
397 usage_with_options(ls_tree_usage
, ls_tree_options
);
398 if (get_oid(argv
[0], &oid
))
399 die("Not a valid object name %s", argv
[0]);
402 * show_recursive() rolls its own matching code and is
403 * generally ignorant of 'struct pathspec'. The magic mask
404 * cannot be lifted until it is converted to use
405 * match_pathspec() or tree_entry_interesting()
407 parse_pathspec(&pathspec
, PATHSPEC_ALL_MAGIC
&
408 ~(PATHSPEC_FROMTOP
| PATHSPEC_LITERAL
),
411 for (i
= 0; i
< pathspec
.nr
; i
++)
412 pathspec
.items
[i
].nowildcard_len
= pathspec
.items
[i
].len
;
413 pathspec
.has_wildcard
= 0;
414 tree
= parse_tree_indirect(&oid
);
416 die("not a tree object");
418 * The generic show_tree_fmt() is slower than show_tree(), so
419 * take the fast path if possible.
423 fn
= format
? show_tree_fmt
: show_tree_default
;
424 } else if (format
&& !strcmp(format
, m2f
->fmt
)) {
427 } else if (!format
&& cmdmode
== m2f
->mode
) {
436 return !!read_tree(the_repository
, tree
, &pathspec
, fn
, NULL
);