blob: e4a891337c3c619112af77bac014139b520e463f [file] [log] [blame]
Petr Baudis7912c072005-04-13 02:02:34 -07001/*
2 * GIT - The information manager from hell
3 *
4 * Copyright (C) Linus Torvalds, 2005
5 */
Elijah Newrenbc5c5ec2023-05-16 06:33:57 +00006#include "builtin.h"
Brandon Williamsb2141fc2017-06-14 11:07:36 -07007#include "config.h"
Elijah Newrenf394e092023-03-21 06:25:54 +00008#include "gettext.h"
Elijah Newren41771fa2023-02-24 00:09:27 +00009#include "hex.h"
Elijah Newrendabab1d2023-04-11 00:41:49 -070010#include "object-name.h"
Elijah Newrena034e912023-05-16 06:34:06 +000011#include "object-store-ll.h"
Junio C Hamano6af1f012005-05-28 00:05:38 -070012#include "tree.h"
Elijah Newrenc3399322023-05-16 06:33:59 +000013#include "path.h"
Junio C Hamano22ddf712005-10-14 21:56:46 -070014#include "quote.h"
Stephen Boyd61fdbcf2009-11-13 20:34:08 -080015#include "parse-options.h"
Nguyễn Thái Ngọc Duy64acde92013-07-14 15:35:25 +070016#include "pathspec.h"
Petr Baudis7912c072005-04-13 02:02:34 -070017
Teng Long925a7c62023-01-12 17:11:34 +080018static const char * const ls_tree_usage[] = {
Nguyễn Thái Ngọc Duy373f9222012-08-20 19:32:21 +070019 N_("git ls-tree [<options>] <tree-ish> [<path>...]"),
Stephen Boyd61fdbcf2009-11-13 20:34:08 -080020 NULL
21};
Linus Torvalds0f8f45c2005-12-01 10:35:51 -080022
Ævar Arnfjörð Bjarmason455923e2022-03-23 17:13:12 +080023static void expand_objectsize(struct strbuf *line, const struct object_id *oid,
24 const enum object_type type, unsigned int padded)
25{
26 if (type == OBJ_BLOB) {
27 unsigned long size;
28 if (oid_object_info(the_repository, oid, &size) < 0)
29 die(_("could not get object info about '%s'"),
30 oid_to_hex(oid));
31 if (padded)
32 strbuf_addf(line, "%7"PRIuMAX, (uintmax_t)size);
33 else
34 strbuf_addf(line, "%"PRIuMAX, (uintmax_t)size);
35 } else if (padded) {
36 strbuf_addf(line, "%7s", "-");
37 } else {
38 strbuf_addstr(line, "-");
39 }
40}
41
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +080042struct ls_tree_options {
Ævar Arnfjörð Bjarmasone6c75d82023-01-12 17:11:33 +080043 unsigned null_termination:1;
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +080044 int abbrev;
45 enum ls_tree_path_options {
46 LS_RECURSIVE = 1 << 0,
47 LS_TREE_ONLY = 1 << 1,
48 LS_SHOW_TREES = 1 << 2,
49 } ls_options;
50 struct pathspec pathspec;
René Scharfe7b7203e2023-07-07 20:34:31 +020051 const char *prefix;
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +080052 const char *format;
53};
54
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +080055static int show_recursive(struct ls_tree_options *options, const char *base,
56 size_t baselen, const char *pathname)
Linus Torvalds0f8f45c2005-12-01 10:35:51 -080057{
Brandon Williamse1e24ed2017-01-04 10:03:59 -080058 int i;
Linus Torvalds0f8f45c2005-12-01 10:35:51 -080059
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +080060 if (options->ls_options & LS_RECURSIVE)
Linus Torvalds0f8f45c2005-12-01 10:35:51 -080061 return 1;
62
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +080063 if (!options->pathspec.nr)
Linus Torvalds0f8f45c2005-12-01 10:35:51 -080064 return 0;
65
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +080066 for (i = 0; i < options->pathspec.nr; i++) {
67 const char *spec = options->pathspec.items[i].match;
Ævar Arnfjörð Bjarmason132ceda2022-03-23 17:13:05 +080068 size_t len, speclen;
Linus Torvalds0f8f45c2005-12-01 10:35:51 -080069
Linus Torvalds0f8f45c2005-12-01 10:35:51 -080070 if (strncmp(base, spec, baselen))
71 continue;
72 len = strlen(pathname);
73 spec += baselen;
74 speclen = strlen(spec);
75 if (speclen <= len)
76 continue;
Junio C Hamanob294ed62010-09-11 11:47:09 -070077 if (spec[len] && spec[len] != '/')
78 continue;
Linus Torvalds0f8f45c2005-12-01 10:35:51 -080079 if (memcmp(pathname, spec, len))
80 continue;
81 return 1;
82 }
Brandon Williamse1e24ed2017-01-04 10:03:59 -080083 return 0;
Linus Torvalds0f8f45c2005-12-01 10:35:51 -080084}
Junio C Hamanoaa1c48d2005-04-15 08:37:05 -070085
Ævar Arnfjörð Bjarmason455923e2022-03-23 17:13:12 +080086static int show_tree_fmt(const struct object_id *oid, struct strbuf *base,
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +080087 const char *pathname, unsigned mode, void *context)
Petr Baudis7912c072005-04-13 02:02:34 -070088{
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +080089 struct ls_tree_options *options = context;
Ævar Arnfjörð Bjarmason455923e2022-03-23 17:13:12 +080090 int recurse = 0;
91 struct strbuf sb = STRBUF_INIT;
92 enum object_type type = object_type(mode);
René Scharfe6f1e2d52023-06-17 22:43:17 +020093 const char *format = options->format;
Ævar Arnfjörð Bjarmason455923e2022-03-23 17:13:12 +080094
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +080095 if (type == OBJ_TREE && show_recursive(options, base->buf, base->len, pathname))
Ævar Arnfjörð Bjarmason455923e2022-03-23 17:13:12 +080096 recurse = READ_TREE_RECURSIVE;
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +080097 if (type == OBJ_TREE && recurse && !(options->ls_options & LS_SHOW_TREES))
Ævar Arnfjörð Bjarmason455923e2022-03-23 17:13:12 +080098 return recurse;
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +080099 if (type == OBJ_BLOB && (options->ls_options & LS_TREE_ONLY))
Junio C Hamanof5984672005-12-01 13:15:20 -0800100 return 0;
Linus Torvalds3c5e8462005-11-26 09:38:20 -0800101
René Scharfe6f1e2d52023-06-17 22:43:17 +0200102 while (strbuf_expand_step(&sb, &format)) {
103 const char *end;
104 size_t len;
105
106 if (skip_prefix(format, "%", &format))
107 strbuf_addch(&sb, '%');
René Scharfe4416b862023-06-17 22:44:00 +0200108 else if ((len = strbuf_expand_literal(&sb, format)))
René Scharfe6f1e2d52023-06-17 22:43:17 +0200109 format += len;
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)) {
127 const char *name;
René Scharfe7b7203e2023-07-07 20:34:31 +0200128 const char *prefix = options->prefix;
René Scharfe6f1e2d52023-06-17 22:43:17 +0200129 struct strbuf sbuf = STRBUF_INIT;
130 size_t baselen = base->len;
131
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);
137 } else
138 die(_("bad ls-tree format: %%%.*s"),
139 (int)(end - format + 1), format);
140 }
Ævar Arnfjörð Bjarmasone6c75d82023-01-12 17:11:33 +0800141 strbuf_addch(&sb, options->null_termination ? '\0' : '\n');
Ævar Arnfjörð Bjarmason455923e2022-03-23 17:13:12 +0800142 fwrite(sb.buf, sb.len, 1, stdout);
143 strbuf_release(&sb);
Ævar Arnfjörð Bjarmason455923e2022-03-23 17:13:12 +0800144 return recurse;
145}
146
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +0800147static int show_tree_common(struct ls_tree_options *options, int *recurse,
148 struct strbuf *base, const char *pathname,
149 enum object_type type)
Teng Long315f22c2022-03-23 17:13:09 +0800150{
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800151 int ret = -1;
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800152 *recurse = 0;
Petr Baudis7912c072005-04-13 02:02:34 -0700153
Teng Long87af0dd2022-03-23 17:13:07 +0800154 if (type == OBJ_BLOB) {
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +0800155 if (options->ls_options & LS_TREE_ONLY)
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800156 ret = 0;
Teng Long87af0dd2022-03-23 17:13:07 +0800157 } else if (type == OBJ_TREE &&
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +0800158 show_recursive(options, base->buf, base->len, pathname)) {
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800159 *recurse = READ_TREE_RECURSIVE;
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +0800160 if (!(options->ls_options & LS_SHOW_TREES))
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800161 ret = *recurse;
Linus Torvalds3c5e8462005-11-26 09:38:20 -0800162 }
Linus Torvalds3c5e8462005-11-26 09:38:20 -0800163
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800164 return ret;
165}
166
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +0800167static void show_tree_common_default_long(struct ls_tree_options *options,
168 struct strbuf *base,
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800169 const char *pathname,
170 const size_t baselen)
171{
René Scharfe7b7203e2023-07-07 20:34:31 +0200172 const char *prefix = options->prefix;
Ævar Arnfjörð Bjarmasone6c75d82023-01-12 17:11:33 +0800173
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800174 strbuf_addstr(base, pathname);
Ævar Arnfjörð Bjarmasone6c75d82023-01-12 17:11:33 +0800175
176 if (options->null_termination) {
177 struct strbuf sb = STRBUF_INIT;
178 const char *name = relative_path(base->buf, prefix, &sb);
179
180 fputs(name, stdout);
181 fputc('\0', stdout);
182
183 strbuf_release(&sb);
184 } else {
185 write_name_quoted_relative(base->buf, prefix, stdout, '\n');
186 }
187
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800188 strbuf_setlen(base, baselen);
189}
190
191static int show_tree_default(const struct object_id *oid, struct strbuf *base,
192 const char *pathname, unsigned mode,
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +0800193 void *context)
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800194{
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +0800195 struct ls_tree_options *options = context;
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800196 int early;
197 int recurse;
Ævar Arnfjörð Bjarmason76774172023-01-12 17:11:30 +0800198 enum object_type type = object_type(mode);
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800199
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +0800200 early = show_tree_common(options, &recurse, base, pathname, type);
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800201 if (early >= 0)
202 return early;
203
Ævar Arnfjörð Bjarmason76774172023-01-12 17:11:30 +0800204 printf("%06o %s %s\t", mode, type_name(object_type(mode)),
Ævar Arnfjörð Bjarmasond850b7a2023-03-28 15:58:46 +0200205 repo_find_unique_abbrev(the_repository, oid, options->abbrev));
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +0800206 show_tree_common_default_long(options, base, pathname, base->len);
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800207 return recurse;
208}
209
210static int show_tree_long(const struct object_id *oid, struct strbuf *base,
Jeff King555ff1c2022-08-19 06:08:49 -0400211 const char *pathname, unsigned mode,
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +0800212 void *context)
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800213{
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +0800214 struct ls_tree_options *options = context;
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800215 int early;
216 int recurse;
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800217 char size_text[24];
Ævar Arnfjörð Bjarmason76774172023-01-12 17:11:30 +0800218 enum object_type type = object_type(mode);
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800219
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +0800220 early = show_tree_common(options, &recurse, base, pathname, type);
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800221 if (early >= 0)
222 return early;
223
Ævar Arnfjörð Bjarmason76774172023-01-12 17:11:30 +0800224 if (type == OBJ_BLOB) {
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800225 unsigned long size;
Ævar Arnfjörð Bjarmason76774172023-01-12 17:11:30 +0800226 if (oid_object_info(the_repository, oid, &size) == OBJ_BAD)
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800227 xsnprintf(size_text, sizeof(size_text), "BAD");
228 else
229 xsnprintf(size_text, sizeof(size_text),
230 "%" PRIuMAX, (uintmax_t)size);
231 } else {
232 xsnprintf(size_text, sizeof(size_text), "-");
Teng Longcab851c2022-03-23 17:13:13 +0800233 }
234
Ævar Arnfjörð Bjarmason76774172023-01-12 17:11:30 +0800235 printf("%06o %s %s %7s\t", mode, type_name(type),
Ævar Arnfjörð Bjarmasond850b7a2023-03-28 15:58:46 +0200236 repo_find_unique_abbrev(the_repository, oid, options->abbrev),
237 size_text);
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +0800238 show_tree_common_default_long(options, base, pathname, base->len);
Josh Steadmon350296c2022-04-04 15:42:24 -0700239 return recurse;
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800240}
Teng Long315f22c2022-03-23 17:13:09 +0800241
Jeff Kingc5cb97c2023-08-29 19:45:19 -0400242static int show_tree_name_only(const struct object_id *oid UNUSED,
243 struct strbuf *base,
Jeff King555ff1c2022-08-19 06:08:49 -0400244 const char *pathname, unsigned mode,
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +0800245 void *context)
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800246{
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +0800247 struct ls_tree_options *options = context;
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800248 int early;
249 int recurse;
250 const size_t baselen = base->len;
Ævar Arnfjörð Bjarmason76774172023-01-12 17:11:30 +0800251 enum object_type type = object_type(mode);
Ævar Arnfjörð Bjarmasone6c75d82023-01-12 17:11:33 +0800252 const char *prefix;
Teng Long315f22c2022-03-23 17:13:09 +0800253
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +0800254 early = show_tree_common(options, &recurse, base, pathname, type);
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800255 if (early >= 0)
256 return early;
257
René Scharfe7b7203e2023-07-07 20:34:31 +0200258 prefix = options->prefix;
Nguyễn Thái Ngọc Duy1cf99522014-11-30 16:05:01 +0700259 strbuf_addstr(base, pathname);
Ævar Arnfjörð Bjarmasone6c75d82023-01-12 17:11:33 +0800260 if (options->null_termination) {
261 struct strbuf sb = STRBUF_INIT;
262 const char *name = relative_path(base->buf, prefix, &sb);
263
264 fputs(name, stdout);
265 fputc('\0', stdout);
266
267 strbuf_release(&sb);
268 } else {
269 write_name_quoted_relative(base->buf, prefix, stdout, '\n');
270 }
Nguyễn Thái Ngọc Duy1cf99522014-11-30 16:05:01 +0700271 strbuf_setlen(base, baselen);
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800272 return recurse;
Linus Torvalds3c5e8462005-11-26 09:38:20 -0800273}
274
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800275static int show_tree_object(const struct object_id *oid, struct strbuf *base,
Jeff King555ff1c2022-08-19 06:08:49 -0400276 const char *pathname, unsigned mode,
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +0800277 void *context)
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800278{
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +0800279 struct ls_tree_options *options = context;
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800280 int early;
281 int recurse;
Ævar Arnfjörð Bjarmason76774172023-01-12 17:11:30 +0800282 enum object_type type = object_type(mode);
Ævar Arnfjörð Bjarmasone6c75d82023-01-12 17:11:33 +0800283 const char *str;
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800284
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +0800285 early = show_tree_common(options, &recurse, base, pathname, type);
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800286 if (early >= 0)
287 return early;
288
Ævar Arnfjörð Bjarmasond850b7a2023-03-28 15:58:46 +0200289 str = repo_find_unique_abbrev(the_repository, oid, options->abbrev);
Ævar Arnfjörð Bjarmasone6c75d82023-01-12 17:11:33 +0800290 if (options->null_termination) {
291 fputs(str, stdout);
292 fputc('\0', stdout);
293 } else {
294 puts(str);
295 }
Teng Long889f7832022-03-23 17:13:06 +0800296 return recurse;
Linus Torvalds3c5e8462005-11-26 09:38:20 -0800297}
298
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +0800299enum ls_tree_cmdmode {
300 MODE_DEFAULT = 0,
301 MODE_LONG,
302 MODE_NAME_ONLY,
303 MODE_NAME_STATUS,
304 MODE_OBJECT_ONLY,
305};
306
Ævar Arnfjörð Bjarmason455923e2022-03-23 17:13:12 +0800307struct ls_tree_cmdmode_to_fmt {
308 enum ls_tree_cmdmode mode;
309 const char *const fmt;
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800310 read_tree_fn_t fn;
Ævar Arnfjörð Bjarmason455923e2022-03-23 17:13:12 +0800311};
312
313static struct ls_tree_cmdmode_to_fmt ls_tree_cmdmode_format[] = {
314 {
315 .mode = MODE_DEFAULT,
316 .fmt = "%(objectmode) %(objecttype) %(objectname)%x09%(path)",
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800317 .fn = show_tree_default,
Ævar Arnfjörð Bjarmason455923e2022-03-23 17:13:12 +0800318 },
319 {
320 .mode = MODE_LONG,
321 .fmt = "%(objectmode) %(objecttype) %(objectname) %(objectsize:padded)%x09%(path)",
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800322 .fn = show_tree_long,
Ævar Arnfjörð Bjarmason455923e2022-03-23 17:13:12 +0800323 },
324 {
325 .mode = MODE_NAME_ONLY, /* And MODE_NAME_STATUS */
326 .fmt = "%(path)",
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800327 .fn = show_tree_name_only,
Ævar Arnfjörð Bjarmason455923e2022-03-23 17:13:12 +0800328 },
Teng Longcab851c2022-03-23 17:13:13 +0800329 {
330 .mode = MODE_OBJECT_ONLY,
331 .fmt = "%(objectname)",
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800332 .fn = show_tree_object
Teng Longcab851c2022-03-23 17:13:13 +0800333 },
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800334 {
335 /* fallback */
336 .fn = show_tree_default,
337 },
Ævar Arnfjörð Bjarmason455923e2022-03-23 17:13:12 +0800338};
339
Linus Torvaldsa633fca2006-07-28 22:44:25 -0700340int cmd_ls_tree(int argc, const char **argv, const char *prefix)
Linus Torvalds3c5e8462005-11-26 09:38:20 -0800341{
brian m. carlsona9b5f5b2017-05-06 22:10:34 +0000342 struct object_id oid;
Daniel Barkalow521698b2006-01-26 01:13:36 -0500343 struct tree *tree;
Nguyễn Thái Ngọc Duyf0096c02011-03-25 16:34:19 +0700344 int i, full_tree = 0;
René Scharfe991c5522023-07-18 17:44:13 +0200345 int full_name = !prefix || !*prefix;
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800346 read_tree_fn_t fn = NULL;
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +0800347 enum ls_tree_cmdmode cmdmode = MODE_DEFAULT;
Ævar Arnfjörð Bjarmasone6c75d82023-01-12 17:11:33 +0800348 int null_termination = 0;
349 struct ls_tree_options options = { 0 };
Stephen Boyd61fdbcf2009-11-13 20:34:08 -0800350 const struct option ls_tree_options[] = {
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +0800351 OPT_BIT('d', NULL, &options.ls_options, N_("only show trees"),
Stephen Boyd61fdbcf2009-11-13 20:34:08 -0800352 LS_TREE_ONLY),
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +0800353 OPT_BIT('r', NULL, &options.ls_options, N_("recurse into subtrees"),
Stephen Boyd61fdbcf2009-11-13 20:34:08 -0800354 LS_RECURSIVE),
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +0800355 OPT_BIT('t', NULL, &options.ls_options, N_("show trees when recursing"),
Stephen Boyd61fdbcf2009-11-13 20:34:08 -0800356 LS_SHOW_TREES),
Ævar Arnfjörð Bjarmasone6c75d82023-01-12 17:11:33 +0800357 OPT_BOOL('z', NULL, &null_termination,
358 N_("terminate entries with NUL byte")),
Teng Long315f22c2022-03-23 17:13:09 +0800359 OPT_CMDMODE('l', "long", &cmdmode, N_("include object size"),
360 MODE_LONG),
361 OPT_CMDMODE(0, "name-only", &cmdmode, N_("list only filenames"),
362 MODE_NAME_ONLY),
363 OPT_CMDMODE(0, "name-status", &cmdmode, N_("list only filenames"),
Ævar Arnfjörð Bjarmason0f887832022-03-23 17:13:14 +0800364 MODE_NAME_STATUS),
Teng Longcab851c2022-03-23 17:13:13 +0800365 OPT_CMDMODE(0, "object-only", &cmdmode, N_("list only objects"),
366 MODE_OBJECT_ONLY),
René Scharfe991c5522023-07-18 17:44:13 +0200367 OPT_BOOL(0, "full-name", &full_name, N_("use full path names")),
Stefan Bellerd5d09d42013-08-03 13:51:19 +0200368 OPT_BOOL(0, "full-tree", &full_tree,
369 N_("list entire tree; not just current directory "
370 "(implies --full-name)")),
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +0800371 OPT_STRING_F(0, "format", &options.format, N_("format"),
Ævar Arnfjörð Bjarmason455923e2022-03-23 17:13:12 +0800372 N_("format to use for the output"),
373 PARSE_OPT_NONEG),
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +0800374 OPT__ABBREV(&options.abbrev),
Stephen Boyd61fdbcf2009-11-13 20:34:08 -0800375 OPT_END()
376 };
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800377 struct ls_tree_cmdmode_to_fmt *m2f = ls_tree_cmdmode_format;
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +0800378 int ret;
Linus Torvalds3c5e8462005-11-26 09:38:20 -0800379
Johannes Schindelinef90d6d2008-05-14 18:46:53 +0100380 git_config(git_default_config, NULL);
Stephen Boyd61fdbcf2009-11-13 20:34:08 -0800381
382 argc = parse_options(argc, argv, prefix, ls_tree_options,
383 ls_tree_usage, 0);
Ævar Arnfjörð Bjarmasone6c75d82023-01-12 17:11:33 +0800384 options.null_termination = null_termination;
385
René Scharfe7b7203e2023-07-07 20:34:31 +0200386 if (full_tree)
387 prefix = NULL;
René Scharfe991c5522023-07-18 17:44:13 +0200388 options.prefix = full_name ? NULL : prefix;
René Scharfe7b7203e2023-07-07 20:34:31 +0200389
Ævar Arnfjörð Bjarmason0f887832022-03-23 17:13:14 +0800390 /*
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.
394 */
395 if (cmdmode == MODE_NAME_STATUS)
396 cmdmode = MODE_NAME_ONLY;
397
Junio C Hamanof5984672005-12-01 13:15:20 -0800398 /* -d -r should imply -t, but -d by itself should not have to. */
399 if ( (LS_TREE_ONLY|LS_RECURSIVE) ==
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +0800400 ((LS_TREE_ONLY|LS_RECURSIVE) & options.ls_options))
401 options.ls_options |= LS_SHOW_TREES;
Junio C Hamanoaa1c48d2005-04-15 08:37:05 -0700402
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +0800403 if (options.format && cmdmode)
Ævar Arnfjörð Bjarmason455923e2022-03-23 17:13:12 +0800404 usage_msg_opt(
405 _("--format can't be combined with other format-altering options"),
406 ls_tree_usage, ls_tree_options);
Stephen Boyd61fdbcf2009-11-13 20:34:08 -0800407 if (argc < 1)
408 usage_with_options(ls_tree_usage, ls_tree_options);
Ævar Arnfjörð Bjarmasond850b7a2023-03-28 15:58:46 +0200409 if (repo_get_oid(the_repository, argv[0], &oid))
Stephen Boyd61fdbcf2009-11-13 20:34:08 -0800410 die("Not a valid object name %s", argv[0]);
Junio C Hamano6af1f012005-05-28 00:05:38 -0700411
Nguyễn Thái Ngọc Duy0fdc2ae2013-07-14 15:35:31 +0700412 /*
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
Nguyễn Thái Ngọc Duy854b0952014-01-24 20:40:30 +0700416 * match_pathspec() or tree_entry_interesting()
Nguyễn Thái Ngọc Duy0fdc2ae2013-07-14 15:35:31 +0700417 */
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +0800418 parse_pathspec(&options.pathspec, PATHSPEC_ALL_MAGIC &
419 ~(PATHSPEC_FROMTOP | PATHSPEC_LITERAL),
Nguyễn Thái Ngọc Duy0fdc2ae2013-07-14 15:35:31 +0700420 PATHSPEC_PREFER_CWD,
421 prefix, argv + 1);
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +0800422 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;
brian m. carlsona9dbc172017-05-06 22:10:37 +0000425 tree = parse_tree_indirect(&oid);
Daniel Barkalow521698b2006-01-26 01:13:36 -0500426 if (!tree)
Linus Torvalds3c5e8462005-11-26 09:38:20 -0800427 die("not a tree object");
Ævar Arnfjörð Bjarmason455923e2022-03-23 17:13:12 +0800428 /*
429 * The generic show_tree_fmt() is slower than show_tree(), so
430 * take the fast path if possible.
431 */
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800432 while (m2f) {
433 if (!m2f->fmt) {
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +0800434 fn = options.format ? show_tree_fmt : show_tree_default;
435 } else if (options.format && !strcmp(options.format, m2f->fmt)) {
Ævar Arnfjörð Bjarmason455923e2022-03-23 17:13:12 +0800436 cmdmode = m2f->mode;
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800437 fn = m2f->fn;
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +0800438 } else if (!options.format && cmdmode == m2f->mode) {
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800439 fn = m2f->fn;
440 } else {
441 m2f++;
442 continue;
Ævar Arnfjörð Bjarmason455923e2022-03-23 17:13:12 +0800443 }
Ævar Arnfjörð Bjarmason9c4d58f2022-03-23 17:13:15 +0800444 break;
Ævar Arnfjörð Bjarmason455923e2022-03-23 17:13:12 +0800445 }
446
Ævar Arnfjörð Bjarmason030a3d52023-01-12 17:11:31 +0800447 ret = !!read_tree(the_repository, tree, &options.pathspec, fn, &options);
448 clear_pathspec(&options.pathspec);
449 return ret;
Petr Baudis7912c072005-04-13 02:02:34 -0700450}