Petr Baudis | 7912c07 | 2005-04-13 02:02:34 -0700 | [diff] [blame] | 1 | /* |
| 2 | * GIT - The information manager from hell |
| 3 | * |
| 4 | * Copyright (C) Linus Torvalds, 2005 |
| 5 | */ |
Elijah Newren | bc5c5ec | 2023-05-16 06:33:57 +0000 | [diff] [blame] | 6 | #include "builtin.h" |
Brandon Williams | b2141fc | 2017-06-14 11:07:36 -0700 | [diff] [blame] | 7 | #include "config.h" |
Elijah Newren | f394e09 | 2023-03-21 06:25:54 +0000 | [diff] [blame] | 8 | #include "gettext.h" |
Elijah Newren | 41771fa | 2023-02-24 00:09:27 +0000 | [diff] [blame] | 9 | #include "hex.h" |
Elijah Newren | dabab1d | 2023-04-11 00:41:49 -0700 | [diff] [blame] | 10 | #include "object-name.h" |
Elijah Newren | a034e91 | 2023-05-16 06:34:06 +0000 | [diff] [blame] | 11 | #include "object-store-ll.h" |
Junio C Hamano | 6af1f01 | 2005-05-28 00:05:38 -0700 | [diff] [blame] | 12 | #include "tree.h" |
Elijah Newren | c339932 | 2023-05-16 06:33:59 +0000 | [diff] [blame] | 13 | #include "path.h" |
Junio C Hamano | 22ddf71 | 2005-10-14 21:56:46 -0700 | [diff] [blame] | 14 | #include "quote.h" |
Stephen Boyd | 61fdbcf | 2009-11-13 20:34:08 -0800 | [diff] [blame] | 15 | #include "parse-options.h" |
Nguyễn Thái Ngọc Duy | 64acde9 | 2013-07-14 15:35:25 +0700 | [diff] [blame] | 16 | #include "pathspec.h" |
Petr Baudis | 7912c07 | 2005-04-13 02:02:34 -0700 | [diff] [blame] | 17 | |
Teng Long | 925a7c6 | 2023-01-12 17:11:34 +0800 | [diff] [blame] | 18 | static const char * const ls_tree_usage[] = { |
Nguyễn Thái Ngọc Duy | 373f922 | 2012-08-20 19:32:21 +0700 | [diff] [blame] | 19 | N_("git ls-tree [<options>] <tree-ish> [<path>...]"), |
Stephen Boyd | 61fdbcf | 2009-11-13 20:34:08 -0800 | [diff] [blame] | 20 | NULL |
| 21 | }; |
Linus Torvalds | 0f8f45c | 2005-12-01 10:35:51 -0800 | [diff] [blame] | 22 | |
Ævar Arnfjörð Bjarmason | 455923e | 2022-03-23 17:13:12 +0800 | [diff] [blame] | 23 | static 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ð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 42 | struct ls_tree_options { |
Ævar Arnfjörð Bjarmason | e6c75d8 | 2023-01-12 17:11:33 +0800 | [diff] [blame] | 43 | unsigned null_termination:1; |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 44 | 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é Scharfe | 7b7203e | 2023-07-07 20:34:31 +0200 | [diff] [blame] | 51 | const char *prefix; |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 52 | const char *format; |
| 53 | }; |
| 54 | |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 55 | static int show_recursive(struct ls_tree_options *options, const char *base, |
| 56 | size_t baselen, const char *pathname) |
Linus Torvalds | 0f8f45c | 2005-12-01 10:35:51 -0800 | [diff] [blame] | 57 | { |
Brandon Williams | e1e24ed | 2017-01-04 10:03:59 -0800 | [diff] [blame] | 58 | int i; |
Linus Torvalds | 0f8f45c | 2005-12-01 10:35:51 -0800 | [diff] [blame] | 59 | |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 60 | if (options->ls_options & LS_RECURSIVE) |
Linus Torvalds | 0f8f45c | 2005-12-01 10:35:51 -0800 | [diff] [blame] | 61 | return 1; |
| 62 | |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 63 | if (!options->pathspec.nr) |
Linus Torvalds | 0f8f45c | 2005-12-01 10:35:51 -0800 | [diff] [blame] | 64 | return 0; |
| 65 | |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 66 | for (i = 0; i < options->pathspec.nr; i++) { |
| 67 | const char *spec = options->pathspec.items[i].match; |
Ævar Arnfjörð Bjarmason | 132ceda | 2022-03-23 17:13:05 +0800 | [diff] [blame] | 68 | size_t len, speclen; |
Linus Torvalds | 0f8f45c | 2005-12-01 10:35:51 -0800 | [diff] [blame] | 69 | |
Linus Torvalds | 0f8f45c | 2005-12-01 10:35:51 -0800 | [diff] [blame] | 70 | 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 Hamano | b294ed6 | 2010-09-11 11:47:09 -0700 | [diff] [blame] | 77 | if (spec[len] && spec[len] != '/') |
| 78 | continue; |
Linus Torvalds | 0f8f45c | 2005-12-01 10:35:51 -0800 | [diff] [blame] | 79 | if (memcmp(pathname, spec, len)) |
| 80 | continue; |
| 81 | return 1; |
| 82 | } |
Brandon Williams | e1e24ed | 2017-01-04 10:03:59 -0800 | [diff] [blame] | 83 | return 0; |
Linus Torvalds | 0f8f45c | 2005-12-01 10:35:51 -0800 | [diff] [blame] | 84 | } |
Junio C Hamano | aa1c48d | 2005-04-15 08:37:05 -0700 | [diff] [blame] | 85 | |
Ævar Arnfjörð Bjarmason | 455923e | 2022-03-23 17:13:12 +0800 | [diff] [blame] | 86 | static int show_tree_fmt(const struct object_id *oid, struct strbuf *base, |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 87 | const char *pathname, unsigned mode, void *context) |
Petr Baudis | 7912c07 | 2005-04-13 02:02:34 -0700 | [diff] [blame] | 88 | { |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 89 | struct ls_tree_options *options = context; |
Ævar Arnfjörð Bjarmason | 455923e | 2022-03-23 17:13:12 +0800 | [diff] [blame] | 90 | int recurse = 0; |
| 91 | struct strbuf sb = STRBUF_INIT; |
| 92 | enum object_type type = object_type(mode); |
René Scharfe | 6f1e2d5 | 2023-06-17 22:43:17 +0200 | [diff] [blame] | 93 | const char *format = options->format; |
Ævar Arnfjörð Bjarmason | 455923e | 2022-03-23 17:13:12 +0800 | [diff] [blame] | 94 | |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 95 | if (type == OBJ_TREE && show_recursive(options, base->buf, base->len, pathname)) |
Ævar Arnfjörð Bjarmason | 455923e | 2022-03-23 17:13:12 +0800 | [diff] [blame] | 96 | recurse = READ_TREE_RECURSIVE; |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 97 | if (type == OBJ_TREE && recurse && !(options->ls_options & LS_SHOW_TREES)) |
Ævar Arnfjörð Bjarmason | 455923e | 2022-03-23 17:13:12 +0800 | [diff] [blame] | 98 | return recurse; |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 99 | if (type == OBJ_BLOB && (options->ls_options & LS_TREE_ONLY)) |
Junio C Hamano | f598467 | 2005-12-01 13:15:20 -0800 | [diff] [blame] | 100 | return 0; |
Linus Torvalds | 3c5e846 | 2005-11-26 09:38:20 -0800 | [diff] [blame] | 101 | |
René Scharfe | 6f1e2d5 | 2023-06-17 22:43:17 +0200 | [diff] [blame] | 102 | 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é Scharfe | 4416b86 | 2023-06-17 22:44:00 +0200 | [diff] [blame] | 108 | else if ((len = strbuf_expand_literal(&sb, format))) |
René Scharfe | 6f1e2d5 | 2023-06-17 22:43:17 +0200 | [diff] [blame] | 109 | 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é Scharfe | 7b7203e | 2023-07-07 20:34:31 +0200 | [diff] [blame] | 128 | const char *prefix = options->prefix; |
René Scharfe | 6f1e2d5 | 2023-06-17 22:43:17 +0200 | [diff] [blame] | 129 | 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ð Bjarmason | e6c75d8 | 2023-01-12 17:11:33 +0800 | [diff] [blame] | 141 | strbuf_addch(&sb, options->null_termination ? '\0' : '\n'); |
Ævar Arnfjörð Bjarmason | 455923e | 2022-03-23 17:13:12 +0800 | [diff] [blame] | 142 | fwrite(sb.buf, sb.len, 1, stdout); |
| 143 | strbuf_release(&sb); |
Ævar Arnfjörð Bjarmason | 455923e | 2022-03-23 17:13:12 +0800 | [diff] [blame] | 144 | return recurse; |
| 145 | } |
| 146 | |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 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) |
Teng Long | 315f22c | 2022-03-23 17:13:09 +0800 | [diff] [blame] | 150 | { |
Ævar Arnfjörð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 151 | int ret = -1; |
Ævar Arnfjörð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 152 | *recurse = 0; |
Petr Baudis | 7912c07 | 2005-04-13 02:02:34 -0700 | [diff] [blame] | 153 | |
Teng Long | 87af0dd | 2022-03-23 17:13:07 +0800 | [diff] [blame] | 154 | if (type == OBJ_BLOB) { |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 155 | if (options->ls_options & LS_TREE_ONLY) |
Ævar Arnfjörð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 156 | ret = 0; |
Teng Long | 87af0dd | 2022-03-23 17:13:07 +0800 | [diff] [blame] | 157 | } else if (type == OBJ_TREE && |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 158 | show_recursive(options, base->buf, base->len, pathname)) { |
Ævar Arnfjörð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 159 | *recurse = READ_TREE_RECURSIVE; |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 160 | if (!(options->ls_options & LS_SHOW_TREES)) |
Ævar Arnfjörð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 161 | ret = *recurse; |
Linus Torvalds | 3c5e846 | 2005-11-26 09:38:20 -0800 | [diff] [blame] | 162 | } |
Linus Torvalds | 3c5e846 | 2005-11-26 09:38:20 -0800 | [diff] [blame] | 163 | |
Ævar Arnfjörð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 164 | return ret; |
| 165 | } |
| 166 | |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 167 | static void show_tree_common_default_long(struct ls_tree_options *options, |
| 168 | struct strbuf *base, |
Ævar Arnfjörð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 169 | const char *pathname, |
| 170 | const size_t baselen) |
| 171 | { |
René Scharfe | 7b7203e | 2023-07-07 20:34:31 +0200 | [diff] [blame] | 172 | const char *prefix = options->prefix; |
Ævar Arnfjörð Bjarmason | e6c75d8 | 2023-01-12 17:11:33 +0800 | [diff] [blame] | 173 | |
Ævar Arnfjörð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 174 | strbuf_addstr(base, pathname); |
Ævar Arnfjörð Bjarmason | e6c75d8 | 2023-01-12 17:11:33 +0800 | [diff] [blame] | 175 | |
| 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ð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 188 | strbuf_setlen(base, baselen); |
| 189 | } |
| 190 | |
| 191 | static int show_tree_default(const struct object_id *oid, struct strbuf *base, |
| 192 | const char *pathname, unsigned mode, |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 193 | void *context) |
Ævar Arnfjörð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 194 | { |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 195 | struct ls_tree_options *options = context; |
Ævar Arnfjörð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 196 | int early; |
| 197 | int recurse; |
Ævar Arnfjörð Bjarmason | 7677417 | 2023-01-12 17:11:30 +0800 | [diff] [blame] | 198 | enum object_type type = object_type(mode); |
Ævar Arnfjörð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 199 | |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 200 | early = show_tree_common(options, &recurse, base, pathname, type); |
Ævar Arnfjörð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 201 | if (early >= 0) |
| 202 | return early; |
| 203 | |
Ævar Arnfjörð Bjarmason | 7677417 | 2023-01-12 17:11:30 +0800 | [diff] [blame] | 204 | printf("%06o %s %s\t", mode, type_name(object_type(mode)), |
Ævar Arnfjörð Bjarmason | d850b7a | 2023-03-28 15:58:46 +0200 | [diff] [blame] | 205 | repo_find_unique_abbrev(the_repository, oid, options->abbrev)); |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 206 | show_tree_common_default_long(options, base, pathname, base->len); |
Ævar Arnfjörð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 207 | return recurse; |
| 208 | } |
| 209 | |
| 210 | static int show_tree_long(const struct object_id *oid, struct strbuf *base, |
Jeff King | 555ff1c | 2022-08-19 06:08:49 -0400 | [diff] [blame] | 211 | const char *pathname, unsigned mode, |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 212 | void *context) |
Ævar Arnfjörð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 213 | { |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 214 | struct ls_tree_options *options = context; |
Ævar Arnfjörð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 215 | int early; |
| 216 | int recurse; |
Ævar Arnfjörð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 217 | char size_text[24]; |
Ævar Arnfjörð Bjarmason | 7677417 | 2023-01-12 17:11:30 +0800 | [diff] [blame] | 218 | enum object_type type = object_type(mode); |
Ævar Arnfjörð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 219 | |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 220 | early = show_tree_common(options, &recurse, base, pathname, type); |
Ævar Arnfjörð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 221 | if (early >= 0) |
| 222 | return early; |
| 223 | |
Ævar Arnfjörð Bjarmason | 7677417 | 2023-01-12 17:11:30 +0800 | [diff] [blame] | 224 | if (type == OBJ_BLOB) { |
Ævar Arnfjörð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 225 | unsigned long size; |
Ævar Arnfjörð Bjarmason | 7677417 | 2023-01-12 17:11:30 +0800 | [diff] [blame] | 226 | if (oid_object_info(the_repository, oid, &size) == OBJ_BAD) |
Ævar Arnfjörð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 227 | 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 Long | cab851c | 2022-03-23 17:13:13 +0800 | [diff] [blame] | 233 | } |
| 234 | |
Ævar Arnfjörð Bjarmason | 7677417 | 2023-01-12 17:11:30 +0800 | [diff] [blame] | 235 | printf("%06o %s %s %7s\t", mode, type_name(type), |
Ævar Arnfjörð Bjarmason | d850b7a | 2023-03-28 15:58:46 +0200 | [diff] [blame] | 236 | repo_find_unique_abbrev(the_repository, oid, options->abbrev), |
| 237 | size_text); |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 238 | show_tree_common_default_long(options, base, pathname, base->len); |
Josh Steadmon | 350296c | 2022-04-04 15:42:24 -0700 | [diff] [blame] | 239 | return recurse; |
Ævar Arnfjörð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 240 | } |
Teng Long | 315f22c | 2022-03-23 17:13:09 +0800 | [diff] [blame] | 241 | |
Jeff King | c5cb97c | 2023-08-29 19:45:19 -0400 | [diff] [blame] | 242 | static int show_tree_name_only(const struct object_id *oid UNUSED, |
| 243 | struct strbuf *base, |
Jeff King | 555ff1c | 2022-08-19 06:08:49 -0400 | [diff] [blame] | 244 | const char *pathname, unsigned mode, |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 245 | void *context) |
Ævar Arnfjörð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 246 | { |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 247 | struct ls_tree_options *options = context; |
Ævar Arnfjörð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 248 | int early; |
| 249 | int recurse; |
| 250 | const size_t baselen = base->len; |
Ævar Arnfjörð Bjarmason | 7677417 | 2023-01-12 17:11:30 +0800 | [diff] [blame] | 251 | enum object_type type = object_type(mode); |
Ævar Arnfjörð Bjarmason | e6c75d8 | 2023-01-12 17:11:33 +0800 | [diff] [blame] | 252 | const char *prefix; |
Teng Long | 315f22c | 2022-03-23 17:13:09 +0800 | [diff] [blame] | 253 | |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 254 | early = show_tree_common(options, &recurse, base, pathname, type); |
Ævar Arnfjörð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 255 | if (early >= 0) |
| 256 | return early; |
| 257 | |
René Scharfe | 7b7203e | 2023-07-07 20:34:31 +0200 | [diff] [blame] | 258 | prefix = options->prefix; |
Nguyễn Thái Ngọc Duy | 1cf9952 | 2014-11-30 16:05:01 +0700 | [diff] [blame] | 259 | strbuf_addstr(base, pathname); |
Ævar Arnfjörð Bjarmason | e6c75d8 | 2023-01-12 17:11:33 +0800 | [diff] [blame] | 260 | 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 Duy | 1cf9952 | 2014-11-30 16:05:01 +0700 | [diff] [blame] | 271 | strbuf_setlen(base, baselen); |
Ævar Arnfjörð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 272 | return recurse; |
Linus Torvalds | 3c5e846 | 2005-11-26 09:38:20 -0800 | [diff] [blame] | 273 | } |
| 274 | |
Ævar Arnfjörð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 275 | static int show_tree_object(const struct object_id *oid, struct strbuf *base, |
Jeff King | 555ff1c | 2022-08-19 06:08:49 -0400 | [diff] [blame] | 276 | const char *pathname, unsigned mode, |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 277 | void *context) |
Ævar Arnfjörð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 278 | { |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 279 | struct ls_tree_options *options = context; |
Ævar Arnfjörð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 280 | int early; |
| 281 | int recurse; |
Ævar Arnfjörð Bjarmason | 7677417 | 2023-01-12 17:11:30 +0800 | [diff] [blame] | 282 | enum object_type type = object_type(mode); |
Ævar Arnfjörð Bjarmason | e6c75d8 | 2023-01-12 17:11:33 +0800 | [diff] [blame] | 283 | const char *str; |
Ævar Arnfjörð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 284 | |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 285 | early = show_tree_common(options, &recurse, base, pathname, type); |
Ævar Arnfjörð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 286 | if (early >= 0) |
| 287 | return early; |
| 288 | |
Ævar Arnfjörð Bjarmason | d850b7a | 2023-03-28 15:58:46 +0200 | [diff] [blame] | 289 | str = repo_find_unique_abbrev(the_repository, oid, options->abbrev); |
Ævar Arnfjörð Bjarmason | e6c75d8 | 2023-01-12 17:11:33 +0800 | [diff] [blame] | 290 | if (options->null_termination) { |
| 291 | fputs(str, stdout); |
| 292 | fputc('\0', stdout); |
| 293 | } else { |
| 294 | puts(str); |
| 295 | } |
Teng Long | 889f783 | 2022-03-23 17:13:06 +0800 | [diff] [blame] | 296 | return recurse; |
Linus Torvalds | 3c5e846 | 2005-11-26 09:38:20 -0800 | [diff] [blame] | 297 | } |
| 298 | |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 299 | enum 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ð Bjarmason | 455923e | 2022-03-23 17:13:12 +0800 | [diff] [blame] | 307 | struct ls_tree_cmdmode_to_fmt { |
| 308 | enum ls_tree_cmdmode mode; |
| 309 | const char *const fmt; |
Ævar Arnfjörð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 310 | read_tree_fn_t fn; |
Ævar Arnfjörð Bjarmason | 455923e | 2022-03-23 17:13:12 +0800 | [diff] [blame] | 311 | }; |
| 312 | |
| 313 | static 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ð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 317 | .fn = show_tree_default, |
Ævar Arnfjörð Bjarmason | 455923e | 2022-03-23 17:13:12 +0800 | [diff] [blame] | 318 | }, |
| 319 | { |
| 320 | .mode = MODE_LONG, |
| 321 | .fmt = "%(objectmode) %(objecttype) %(objectname) %(objectsize:padded)%x09%(path)", |
Ævar Arnfjörð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 322 | .fn = show_tree_long, |
Ævar Arnfjörð Bjarmason | 455923e | 2022-03-23 17:13:12 +0800 | [diff] [blame] | 323 | }, |
| 324 | { |
| 325 | .mode = MODE_NAME_ONLY, /* And MODE_NAME_STATUS */ |
| 326 | .fmt = "%(path)", |
Ævar Arnfjörð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 327 | .fn = show_tree_name_only, |
Ævar Arnfjörð Bjarmason | 455923e | 2022-03-23 17:13:12 +0800 | [diff] [blame] | 328 | }, |
Teng Long | cab851c | 2022-03-23 17:13:13 +0800 | [diff] [blame] | 329 | { |
| 330 | .mode = MODE_OBJECT_ONLY, |
| 331 | .fmt = "%(objectname)", |
Ævar Arnfjörð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 332 | .fn = show_tree_object |
Teng Long | cab851c | 2022-03-23 17:13:13 +0800 | [diff] [blame] | 333 | }, |
Ævar Arnfjörð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 334 | { |
| 335 | /* fallback */ |
| 336 | .fn = show_tree_default, |
| 337 | }, |
Ævar Arnfjörð Bjarmason | 455923e | 2022-03-23 17:13:12 +0800 | [diff] [blame] | 338 | }; |
| 339 | |
Linus Torvalds | a633fca | 2006-07-28 22:44:25 -0700 | [diff] [blame] | 340 | int cmd_ls_tree(int argc, const char **argv, const char *prefix) |
Linus Torvalds | 3c5e846 | 2005-11-26 09:38:20 -0800 | [diff] [blame] | 341 | { |
brian m. carlson | a9b5f5b | 2017-05-06 22:10:34 +0000 | [diff] [blame] | 342 | struct object_id oid; |
Daniel Barkalow | 521698b | 2006-01-26 01:13:36 -0500 | [diff] [blame] | 343 | struct tree *tree; |
Nguyễn Thái Ngọc Duy | f0096c0 | 2011-03-25 16:34:19 +0700 | [diff] [blame] | 344 | int i, full_tree = 0; |
René Scharfe | 991c552 | 2023-07-18 17:44:13 +0200 | [diff] [blame] | 345 | int full_name = !prefix || !*prefix; |
Ævar Arnfjörð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 346 | read_tree_fn_t fn = NULL; |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 347 | enum ls_tree_cmdmode cmdmode = MODE_DEFAULT; |
Ævar Arnfjörð Bjarmason | e6c75d8 | 2023-01-12 17:11:33 +0800 | [diff] [blame] | 348 | int null_termination = 0; |
| 349 | struct ls_tree_options options = { 0 }; |
Stephen Boyd | 61fdbcf | 2009-11-13 20:34:08 -0800 | [diff] [blame] | 350 | const struct option ls_tree_options[] = { |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 351 | OPT_BIT('d', NULL, &options.ls_options, N_("only show trees"), |
Stephen Boyd | 61fdbcf | 2009-11-13 20:34:08 -0800 | [diff] [blame] | 352 | LS_TREE_ONLY), |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 353 | OPT_BIT('r', NULL, &options.ls_options, N_("recurse into subtrees"), |
Stephen Boyd | 61fdbcf | 2009-11-13 20:34:08 -0800 | [diff] [blame] | 354 | LS_RECURSIVE), |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 355 | OPT_BIT('t', NULL, &options.ls_options, N_("show trees when recursing"), |
Stephen Boyd | 61fdbcf | 2009-11-13 20:34:08 -0800 | [diff] [blame] | 356 | LS_SHOW_TREES), |
Ævar Arnfjörð Bjarmason | e6c75d8 | 2023-01-12 17:11:33 +0800 | [diff] [blame] | 357 | OPT_BOOL('z', NULL, &null_termination, |
| 358 | N_("terminate entries with NUL byte")), |
Teng Long | 315f22c | 2022-03-23 17:13:09 +0800 | [diff] [blame] | 359 | 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ð Bjarmason | 0f88783 | 2022-03-23 17:13:14 +0800 | [diff] [blame] | 364 | MODE_NAME_STATUS), |
Teng Long | cab851c | 2022-03-23 17:13:13 +0800 | [diff] [blame] | 365 | OPT_CMDMODE(0, "object-only", &cmdmode, N_("list only objects"), |
| 366 | MODE_OBJECT_ONLY), |
René Scharfe | 991c552 | 2023-07-18 17:44:13 +0200 | [diff] [blame] | 367 | OPT_BOOL(0, "full-name", &full_name, N_("use full path names")), |
Stefan Beller | d5d09d4 | 2013-08-03 13:51:19 +0200 | [diff] [blame] | 368 | OPT_BOOL(0, "full-tree", &full_tree, |
| 369 | N_("list entire tree; not just current directory " |
| 370 | "(implies --full-name)")), |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 371 | OPT_STRING_F(0, "format", &options.format, N_("format"), |
Ævar Arnfjörð Bjarmason | 455923e | 2022-03-23 17:13:12 +0800 | [diff] [blame] | 372 | N_("format to use for the output"), |
| 373 | PARSE_OPT_NONEG), |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 374 | OPT__ABBREV(&options.abbrev), |
Stephen Boyd | 61fdbcf | 2009-11-13 20:34:08 -0800 | [diff] [blame] | 375 | OPT_END() |
| 376 | }; |
Ævar Arnfjörð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 377 | struct ls_tree_cmdmode_to_fmt *m2f = ls_tree_cmdmode_format; |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 378 | int ret; |
Linus Torvalds | 3c5e846 | 2005-11-26 09:38:20 -0800 | [diff] [blame] | 379 | |
Johannes Schindelin | ef90d6d | 2008-05-14 18:46:53 +0100 | [diff] [blame] | 380 | git_config(git_default_config, NULL); |
Stephen Boyd | 61fdbcf | 2009-11-13 20:34:08 -0800 | [diff] [blame] | 381 | |
| 382 | argc = parse_options(argc, argv, prefix, ls_tree_options, |
| 383 | ls_tree_usage, 0); |
Ævar Arnfjörð Bjarmason | e6c75d8 | 2023-01-12 17:11:33 +0800 | [diff] [blame] | 384 | options.null_termination = null_termination; |
| 385 | |
René Scharfe | 7b7203e | 2023-07-07 20:34:31 +0200 | [diff] [blame] | 386 | if (full_tree) |
| 387 | prefix = NULL; |
René Scharfe | 991c552 | 2023-07-18 17:44:13 +0200 | [diff] [blame] | 388 | options.prefix = full_name ? NULL : prefix; |
René Scharfe | 7b7203e | 2023-07-07 20:34:31 +0200 | [diff] [blame] | 389 | |
Ævar Arnfjörð Bjarmason | 0f88783 | 2022-03-23 17:13:14 +0800 | [diff] [blame] | 390 | /* |
| 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 Hamano | f598467 | 2005-12-01 13:15:20 -0800 | [diff] [blame] | 398 | /* -d -r should imply -t, but -d by itself should not have to. */ |
| 399 | if ( (LS_TREE_ONLY|LS_RECURSIVE) == |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 400 | ((LS_TREE_ONLY|LS_RECURSIVE) & options.ls_options)) |
| 401 | options.ls_options |= LS_SHOW_TREES; |
Junio C Hamano | aa1c48d | 2005-04-15 08:37:05 -0700 | [diff] [blame] | 402 | |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 403 | if (options.format && cmdmode) |
Ævar Arnfjörð Bjarmason | 455923e | 2022-03-23 17:13:12 +0800 | [diff] [blame] | 404 | usage_msg_opt( |
| 405 | _("--format can't be combined with other format-altering options"), |
| 406 | ls_tree_usage, ls_tree_options); |
Stephen Boyd | 61fdbcf | 2009-11-13 20:34:08 -0800 | [diff] [blame] | 407 | if (argc < 1) |
| 408 | usage_with_options(ls_tree_usage, ls_tree_options); |
Ævar Arnfjörð Bjarmason | d850b7a | 2023-03-28 15:58:46 +0200 | [diff] [blame] | 409 | if (repo_get_oid(the_repository, argv[0], &oid)) |
Stephen Boyd | 61fdbcf | 2009-11-13 20:34:08 -0800 | [diff] [blame] | 410 | die("Not a valid object name %s", argv[0]); |
Junio C Hamano | 6af1f01 | 2005-05-28 00:05:38 -0700 | [diff] [blame] | 411 | |
Nguyễn Thái Ngọc Duy | 0fdc2ae | 2013-07-14 15:35:31 +0700 | [diff] [blame] | 412 | /* |
| 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 Duy | 854b095 | 2014-01-24 20:40:30 +0700 | [diff] [blame] | 416 | * match_pathspec() or tree_entry_interesting() |
Nguyễn Thái Ngọc Duy | 0fdc2ae | 2013-07-14 15:35:31 +0700 | [diff] [blame] | 417 | */ |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 418 | parse_pathspec(&options.pathspec, PATHSPEC_ALL_MAGIC & |
| 419 | ~(PATHSPEC_FROMTOP | PATHSPEC_LITERAL), |
Nguyễn Thái Ngọc Duy | 0fdc2ae | 2013-07-14 15:35:31 +0700 | [diff] [blame] | 420 | PATHSPEC_PREFER_CWD, |
| 421 | prefix, argv + 1); |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 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; |
brian m. carlson | a9dbc17 | 2017-05-06 22:10:37 +0000 | [diff] [blame] | 425 | tree = parse_tree_indirect(&oid); |
Daniel Barkalow | 521698b | 2006-01-26 01:13:36 -0500 | [diff] [blame] | 426 | if (!tree) |
Linus Torvalds | 3c5e846 | 2005-11-26 09:38:20 -0800 | [diff] [blame] | 427 | die("not a tree object"); |
Ævar Arnfjörð Bjarmason | 455923e | 2022-03-23 17:13:12 +0800 | [diff] [blame] | 428 | /* |
| 429 | * The generic show_tree_fmt() is slower than show_tree(), so |
| 430 | * take the fast path if possible. |
| 431 | */ |
Ævar Arnfjörð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 432 | while (m2f) { |
| 433 | if (!m2f->fmt) { |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 434 | fn = options.format ? show_tree_fmt : show_tree_default; |
| 435 | } else if (options.format && !strcmp(options.format, m2f->fmt)) { |
Ævar Arnfjörð Bjarmason | 455923e | 2022-03-23 17:13:12 +0800 | [diff] [blame] | 436 | cmdmode = m2f->mode; |
Ævar Arnfjörð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 437 | fn = m2f->fn; |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 438 | } else if (!options.format && cmdmode == m2f->mode) { |
Ævar Arnfjörð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 439 | fn = m2f->fn; |
| 440 | } else { |
| 441 | m2f++; |
| 442 | continue; |
Ævar Arnfjörð Bjarmason | 455923e | 2022-03-23 17:13:12 +0800 | [diff] [blame] | 443 | } |
Ævar Arnfjörð Bjarmason | 9c4d58f | 2022-03-23 17:13:15 +0800 | [diff] [blame] | 444 | break; |
Ævar Arnfjörð Bjarmason | 455923e | 2022-03-23 17:13:12 +0800 | [diff] [blame] | 445 | } |
| 446 | |
Ævar Arnfjörð Bjarmason | 030a3d5 | 2023-01-12 17:11:31 +0800 | [diff] [blame] | 447 | ret = !!read_tree(the_repository, tree, &options.pathspec, fn, &options); |
| 448 | clear_pathspec(&options.pathspec); |
| 449 | return ret; |
Petr Baudis | 7912c07 | 2005-04-13 02:02:34 -0700 | [diff] [blame] | 450 | } |