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 2
20 #define LS_SHOW_TREES 4
21 #define LS_NAME_ONLY 8
22 #define LS_SHOW_SIZE 16
24 static int ls_options
;
25 static struct pathspec pathspec
;
26 static int chomp_prefix
;
27 static const char *ls_tree_prefix
;
29 static const char * const ls_tree_usage
[] = {
30 N_("git ls-tree [<options>] <tree-ish> [<path>...]"),
34 static int show_recursive(const char *base
, size_t baselen
, const char *pathname
)
38 if (ls_options
& LS_RECURSIVE
)
44 for (i
= 0; i
< pathspec
.nr
; i
++) {
45 const char *spec
= pathspec
.items
[i
].match
;
48 if (strncmp(base
, spec
, baselen
))
50 len
= strlen(pathname
);
52 speclen
= strlen(spec
);
55 if (spec
[len
] && spec
[len
] != '/')
57 if (memcmp(pathname
, spec
, len
))
64 static int show_tree(const struct object_id
*oid
, struct strbuf
*base
,
65 const char *pathname
, unsigned mode
, void *context
)
69 enum object_type type
= object_type(mode
);
71 if (type
== OBJ_BLOB
) {
72 if (ls_options
& LS_TREE_ONLY
)
74 } else if (type
== OBJ_TREE
&&
75 show_recursive(base
->buf
, base
->len
, pathname
)) {
76 recurse
= READ_TREE_RECURSIVE
;
77 if (!(ls_options
& LS_SHOW_TREES
))
81 if (!(ls_options
& LS_NAME_ONLY
)) {
82 if (ls_options
& LS_SHOW_SIZE
) {
84 if (type
== OBJ_BLOB
) {
86 if (oid_object_info(the_repository
, oid
, &size
) == OBJ_BAD
)
87 xsnprintf(size_text
, sizeof(size_text
),
90 xsnprintf(size_text
, sizeof(size_text
),
91 "%"PRIuMAX
, (uintmax_t)size
);
93 xsnprintf(size_text
, sizeof(size_text
), "-");
95 printf("%06o %s %s %7s\t", mode
, type_name(type
),
96 find_unique_abbrev(oid
, abbrev
),
99 printf("%06o %s %s\t", mode
, type_name(type
),
100 find_unique_abbrev(oid
, abbrev
));
104 strbuf_addstr(base
, pathname
);
105 write_name_quoted_relative(base
->buf
,
106 chomp_prefix
? ls_tree_prefix
: NULL
,
107 stdout
, line_termination
);
108 strbuf_setlen(base
, baselen
);
112 int cmd_ls_tree(int argc
, const char **argv
, const char *prefix
)
114 struct object_id oid
;
116 int i
, full_tree
= 0;
117 const struct option ls_tree_options
[] = {
118 OPT_BIT('d', NULL
, &ls_options
, N_("only show trees"),
120 OPT_BIT('r', NULL
, &ls_options
, N_("recurse into subtrees"),
122 OPT_BIT('t', NULL
, &ls_options
, N_("show trees when recursing"),
124 OPT_SET_INT('z', NULL
, &line_termination
,
125 N_("terminate entries with NUL byte"), 0),
126 OPT_BIT('l', "long", &ls_options
, N_("include object size"),
128 OPT_BIT(0, "name-only", &ls_options
, N_("list only filenames"),
130 OPT_BIT(0, "name-status", &ls_options
, N_("list only filenames"),
132 OPT_SET_INT(0, "full-name", &chomp_prefix
,
133 N_("use full path names"), 0),
134 OPT_BOOL(0, "full-tree", &full_tree
,
135 N_("list entire tree; not just current directory "
136 "(implies --full-name)")),
137 OPT__ABBREV(&abbrev
),
141 git_config(git_default_config
, NULL
);
142 ls_tree_prefix
= prefix
;
143 if (prefix
&& *prefix
)
144 chomp_prefix
= strlen(prefix
);
146 argc
= parse_options(argc
, argv
, prefix
, ls_tree_options
,
149 ls_tree_prefix
= prefix
= NULL
;
152 /* -d -r should imply -t, but -d by itself should not have to. */
153 if ( (LS_TREE_ONLY
|LS_RECURSIVE
) ==
154 ((LS_TREE_ONLY
|LS_RECURSIVE
) & ls_options
))
155 ls_options
|= LS_SHOW_TREES
;
158 usage_with_options(ls_tree_usage
, ls_tree_options
);
159 if (get_oid(argv
[0], &oid
))
160 die("Not a valid object name %s", argv
[0]);
163 * show_recursive() rolls its own matching code and is
164 * generally ignorant of 'struct pathspec'. The magic mask
165 * cannot be lifted until it is converted to use
166 * match_pathspec() or tree_entry_interesting()
168 parse_pathspec(&pathspec
, PATHSPEC_ALL_MAGIC
&
169 ~(PATHSPEC_FROMTOP
| PATHSPEC_LITERAL
),
172 for (i
= 0; i
< pathspec
.nr
; i
++)
173 pathspec
.items
[i
].nowildcard_len
= pathspec
.items
[i
].len
;
174 pathspec
.has_wildcard
= 0;
175 tree
= parse_tree_indirect(&oid
);
177 die("not a tree object");
178 return !!read_tree(the_repository
, tree
,
179 &pathspec
, show_tree
, NULL
);