Linus Torvalds | 8695c8b | 2005-04-11 18:55:38 -0700 | [diff] [blame] | 1 | /* |
| 2 | * This merges the file listing in the directory cache index |
| 3 | * with the actual working directory list, and shows different |
| 4 | * combinations of the two. |
| 5 | * |
| 6 | * Copyright (C) Linus Torvalds, 2005 |
| 7 | */ |
Linus Torvalds | 8695c8b | 2005-04-11 18:55:38 -0700 | [diff] [blame] | 8 | #include "cache.h" |
Brandon Williams | 188dce1 | 2017-06-22 11:43:48 -0700 | [diff] [blame] | 9 | #include "repository.h" |
Brandon Williams | b2141fc | 2017-06-14 11:07:36 -0700 | [diff] [blame] | 10 | #include "config.h" |
Junio C Hamano | 22ddf71 | 2005-10-14 21:56:46 -0700 | [diff] [blame] | 11 | #include "quote.h" |
Linus Torvalds | 453ec4b | 2006-05-16 19:02:14 -0700 | [diff] [blame] | 12 | #include "dir.h" |
Peter Eriksen | 0864f26 | 2006-05-23 14:15:29 +0200 | [diff] [blame] | 13 | #include "builtin.h" |
ZheNing Hu | ce74de9 | 2022-07-23 06:44:45 +0000 | [diff] [blame] | 14 | #include "strbuf.h" |
Junio C Hamano | 64586e7 | 2007-09-12 16:04:22 -0700 | [diff] [blame] | 15 | #include "tree.h" |
Ævar Arnfjörð Bjarmason | eefadd1 | 2021-03-20 23:37:46 +0100 | [diff] [blame] | 16 | #include "cache-tree.h" |
Miklos Vajna | ce8e880 | 2009-02-17 15:27:11 +0100 | [diff] [blame] | 17 | #include "parse-options.h" |
Junio C Hamano | 9d9a2f4 | 2009-12-25 10:08:04 -0800 | [diff] [blame] | 18 | #include "resolve-undo.h" |
| 19 | #include "string-list.h" |
Nguyễn Thái Ngọc Duy | 64acde9 | 2013-07-14 15:35:25 +0700 | [diff] [blame] | 20 | #include "pathspec.h" |
Brandon Williams | e77aa33 | 2016-10-07 11:18:49 -0700 | [diff] [blame] | 21 | #include "run-command.h" |
Jacob Keller | 2e5d650 | 2017-04-13 10:12:23 -0700 | [diff] [blame] | 22 | #include "submodule.h" |
Brandon Williams | 1b796ac | 2017-08-03 11:19:57 -0700 | [diff] [blame] | 23 | #include "submodule-config.h" |
Linus Torvalds | 8695c8b | 2005-04-11 18:55:38 -0700 | [diff] [blame] | 24 | |
David Rientjes | 96f1e58 | 2006-08-15 10:23:48 -0700 | [diff] [blame] | 25 | static int abbrev; |
| 26 | static int show_deleted; |
| 27 | static int show_cached; |
| 28 | static int show_others; |
| 29 | static int show_stage; |
| 30 | static int show_unmerged; |
Junio C Hamano | 9d9a2f4 | 2009-12-25 10:08:04 -0800 | [diff] [blame] | 31 | static int show_resolve_undo; |
David Rientjes | 96f1e58 | 2006-08-15 10:23:48 -0700 | [diff] [blame] | 32 | static int show_modified; |
| 33 | static int show_killed; |
| 34 | static int show_valid_bit; |
Ben Peart | d8c71db | 2017-09-22 12:35:42 -0400 | [diff] [blame] | 35 | static int show_fsmonitor_bit; |
Junio C Hamano | b83c834 | 2005-04-15 11:11:01 -0700 | [diff] [blame] | 36 | static int line_terminator = '\n'; |
Thomas Rast | 8497421 | 2010-07-31 00:35:59 +0200 | [diff] [blame] | 37 | static int debug_mode; |
Torsten Bögershausen | a7630bd | 2016-01-16 07:50:02 +0100 | [diff] [blame] | 38 | static int show_eol; |
Brandon Williams | e77aa33 | 2016-10-07 11:18:49 -0700 | [diff] [blame] | 39 | static int recurse_submodules; |
ZheNing Hu | 93a7d98 | 2021-01-23 10:20:10 +0000 | [diff] [blame] | 40 | static int skipping_duplicates; |
Derrick Stolee | 7808709 | 2021-12-22 14:20:53 +0000 | [diff] [blame] | 41 | static int show_sparse_dirs; |
Linus Torvalds | 8695c8b | 2005-04-11 18:55:38 -0700 | [diff] [blame] | 42 | |
Clemens Buchacher | efad1a5 | 2010-06-03 15:39:18 +0200 | [diff] [blame] | 43 | static const char *prefix; |
| 44 | static int max_prefix_len; |
David Rientjes | 96f1e58 | 2006-08-15 10:23:48 -0700 | [diff] [blame] | 45 | static int prefix_len; |
Nguyễn Thái Ngọc Duy | 9e06d6e | 2013-07-14 15:35:43 +0700 | [diff] [blame] | 46 | static struct pathspec pathspec; |
David Rientjes | 96f1e58 | 2006-08-15 10:23:48 -0700 | [diff] [blame] | 47 | static int error_unmatch; |
| 48 | static char *ps_matched; |
Junio C Hamano | 64586e7 | 2007-09-12 16:04:22 -0700 | [diff] [blame] | 49 | static const char *with_tree; |
Miklos Vajna | ce8e880 | 2009-02-17 15:27:11 +0100 | [diff] [blame] | 50 | static int exc_given; |
Adam Spiers | c04318e | 2013-01-06 16:58:04 +0000 | [diff] [blame] | 51 | static int exclude_args; |
ZheNing Hu | ce74de9 | 2022-07-23 06:44:45 +0000 | [diff] [blame] | 52 | static const char *format; |
Linus Torvalds | 5be4efb | 2005-08-21 12:55:33 -0700 | [diff] [blame] | 53 | |
Petr Baudis | 20d37ef | 2005-04-21 19:47:08 -0700 | [diff] [blame] | 54 | static const char *tag_cached = ""; |
| 55 | static const char *tag_unmerged = ""; |
| 56 | static const char *tag_removed = ""; |
| 57 | static const char *tag_other = ""; |
Junio C Hamano | 6ca4594 | 2005-05-12 17:17:54 -0700 | [diff] [blame] | 58 | static const char *tag_killed = ""; |
Junio C Hamano | b039189 | 2005-09-19 15:11:15 -0700 | [diff] [blame] | 59 | static const char *tag_modified = ""; |
Nguyễn Thái Ngọc Duy | 44a3691 | 2009-08-20 20:46:57 +0700 | [diff] [blame] | 60 | static const char *tag_skip_worktree = ""; |
Junio C Hamano | 9d9a2f4 | 2009-12-25 10:08:04 -0800 | [diff] [blame] | 61 | static const char *tag_resolve_undo = ""; |
Petr Baudis | 20d37ef | 2005-04-21 19:47:08 -0700 | [diff] [blame] | 62 | |
Derrick Stolee | 847a9e5 | 2021-04-01 01:49:39 +0000 | [diff] [blame] | 63 | static void write_eolinfo(struct index_state *istate, |
Brandon Williams | 1985fd6 | 2017-06-12 15:13:59 -0700 | [diff] [blame] | 64 | const struct cache_entry *ce, const char *path) |
Torsten Bögershausen | a7630bd | 2016-01-16 07:50:02 +0100 | [diff] [blame] | 65 | { |
Brandon Williams | 1985fd6 | 2017-06-12 15:13:59 -0700 | [diff] [blame] | 66 | if (show_eol) { |
Torsten Bögershausen | a7630bd | 2016-01-16 07:50:02 +0100 | [diff] [blame] | 67 | struct stat st; |
| 68 | const char *i_txt = ""; |
| 69 | const char *w_txt = ""; |
Nguyễn Thái Ngọc Duy | a52b321 | 2018-08-13 18:14:24 +0200 | [diff] [blame] | 70 | const char *a_txt = get_convert_attr_ascii(istate, path); |
Torsten Bögershausen | a7630bd | 2016-01-16 07:50:02 +0100 | [diff] [blame] | 71 | if (ce && S_ISREG(ce->ce_mode)) |
Brandon Williams | 1985fd6 | 2017-06-12 15:13:59 -0700 | [diff] [blame] | 72 | i_txt = get_cached_convert_stats_ascii(istate, |
Brandon Williams | a7609c5 | 2017-06-12 15:13:52 -0700 | [diff] [blame] | 73 | ce->name); |
Torsten Bögershausen | a7630bd | 2016-01-16 07:50:02 +0100 | [diff] [blame] | 74 | if (!lstat(path, &st) && S_ISREG(st.st_mode)) |
| 75 | w_txt = get_wt_convert_stats_ascii(path); |
| 76 | printf("i/%-5s w/%-5s attr/%-17s\t", i_txt, w_txt, a_txt); |
| 77 | } |
| 78 | } |
| 79 | |
Jiang Xin | e9a820c | 2013-06-25 23:53:46 +0800 | [diff] [blame] | 80 | static void write_name(const char *name) |
Clemens Buchacher | efad1a5 | 2010-06-03 15:39:18 +0200 | [diff] [blame] | 81 | { |
Jiang Xin | ad66df2 | 2013-06-25 23:53:44 +0800 | [diff] [blame] | 82 | /* |
Jiang Xin | e9a820c | 2013-06-25 23:53:46 +0800 | [diff] [blame] | 83 | * With "--full-name", prefix_len=0; this caller needs to pass |
| 84 | * an empty string in that case (a NULL is good for ""). |
Jiang Xin | ad66df2 | 2013-06-25 23:53:44 +0800 | [diff] [blame] | 85 | */ |
Jiang Xin | e9a820c | 2013-06-25 23:53:46 +0800 | [diff] [blame] | 86 | write_name_quoted_relative(name, prefix_len ? prefix : NULL, |
| 87 | stdout, line_terminator); |
Clemens Buchacher | efad1a5 | 2010-06-03 15:39:18 +0200 | [diff] [blame] | 88 | } |
| 89 | |
ZheNing Hu | ce74de9 | 2022-07-23 06:44:45 +0000 | [diff] [blame] | 90 | static void write_name_to_buf(struct strbuf *sb, const char *name) |
| 91 | { |
| 92 | const char *rel = relative_path(name, prefix_len ? prefix : NULL, sb); |
| 93 | |
| 94 | if (line_terminator) |
| 95 | quote_c_style(rel, sb, NULL, 0); |
| 96 | else |
| 97 | strbuf_addstr(sb, rel); |
| 98 | } |
| 99 | |
Brandon Williams | a84f3e5 | 2017-06-12 15:14:08 -0700 | [diff] [blame] | 100 | static const char *get_tag(const struct cache_entry *ce, const char *tag) |
| 101 | { |
| 102 | static char alttag[4]; |
| 103 | |
Ben Peart | d8c71db | 2017-09-22 12:35:42 -0400 | [diff] [blame] | 104 | if (tag && *tag && ((show_valid_bit && (ce->ce_flags & CE_VALID)) || |
| 105 | (show_fsmonitor_bit && (ce->ce_flags & CE_FSMONITOR_VALID)))) { |
Brandon Williams | a84f3e5 | 2017-06-12 15:14:08 -0700 | [diff] [blame] | 106 | memcpy(alttag, tag, 3); |
| 107 | |
| 108 | if (isalpha(tag[0])) { |
| 109 | alttag[0] = tolower(tag[0]); |
| 110 | } else if (tag[0] == '?') { |
| 111 | alttag[0] = '!'; |
| 112 | } else { |
| 113 | alttag[0] = 'v'; |
| 114 | alttag[1] = tag[0]; |
| 115 | alttag[2] = ' '; |
| 116 | alttag[3] = 0; |
| 117 | } |
| 118 | |
| 119 | tag = alttag; |
| 120 | } |
| 121 | |
| 122 | return tag; |
| 123 | } |
| 124 | |
Brandon Williams | 5306ccf | 2017-06-12 15:14:07 -0700 | [diff] [blame] | 125 | static void print_debug(const struct cache_entry *ce) |
| 126 | { |
| 127 | if (debug_mode) { |
| 128 | const struct stat_data *sd = &ce->ce_stat_data; |
| 129 | |
Thomas Gummerer | 7cb7283 | 2019-04-07 19:47:51 +0100 | [diff] [blame] | 130 | printf(" ctime: %u:%u\n", sd->sd_ctime.sec, sd->sd_ctime.nsec); |
| 131 | printf(" mtime: %u:%u\n", sd->sd_mtime.sec, sd->sd_mtime.nsec); |
| 132 | printf(" dev: %u\tino: %u\n", sd->sd_dev, sd->sd_ino); |
| 133 | printf(" uid: %u\tgid: %u\n", sd->sd_uid, sd->sd_gid); |
| 134 | printf(" size: %u\tflags: %x\n", sd->sd_size, ce->ce_flags); |
Brandon Williams | 5306ccf | 2017-06-12 15:14:07 -0700 | [diff] [blame] | 135 | } |
| 136 | } |
| 137 | |
Derrick Stolee | 847a9e5 | 2021-04-01 01:49:39 +0000 | [diff] [blame] | 138 | static void show_dir_entry(struct index_state *istate, |
Nguyễn Thái Ngọc Duy | a52b321 | 2018-08-13 18:14:24 +0200 | [diff] [blame] | 139 | const char *tag, struct dir_entry *ent) |
Linus Torvalds | 5be4efb | 2005-08-21 12:55:33 -0700 | [diff] [blame] | 140 | { |
Clemens Buchacher | efad1a5 | 2010-06-03 15:39:18 +0200 | [diff] [blame] | 141 | int len = max_prefix_len; |
Linus Torvalds | 5be4efb | 2005-08-21 12:55:33 -0700 | [diff] [blame] | 142 | |
Brandon Williams | cbca060 | 2017-05-11 15:04:25 -0700 | [diff] [blame] | 143 | if (len > ent->len) |
Junio C Hamano | 7e44c93 | 2008-08-31 09:39:19 -0700 | [diff] [blame] | 144 | die("git ls-files: internal error - directory entry not superset of prefix"); |
Linus Torvalds | 5be4efb | 2005-08-21 12:55:33 -0700 | [diff] [blame] | 145 | |
Elijah Newren | 95c11ec | 2020-04-01 04:17:45 +0000 | [diff] [blame] | 146 | /* If ps_matches is non-NULL, figure out which pathspec(s) match. */ |
| 147 | if (ps_matched) |
| 148 | dir_path_match(istate, ent, &pathspec, len, ps_matched); |
Linus Torvalds | 5be4efb | 2005-08-21 12:55:33 -0700 | [diff] [blame] | 149 | |
Junio C Hamano | 22ddf71 | 2005-10-14 21:56:46 -0700 | [diff] [blame] | 150 | fputs(tag, stdout); |
Nguyễn Thái Ngọc Duy | a52b321 | 2018-08-13 18:14:24 +0200 | [diff] [blame] | 151 | write_eolinfo(istate, NULL, ent->name); |
Jiang Xin | e9a820c | 2013-06-25 23:53:46 +0800 | [diff] [blame] | 152 | write_name(ent->name); |
Linus Torvalds | 5be4efb | 2005-08-21 12:55:33 -0700 | [diff] [blame] | 153 | } |
| 154 | |
Derrick Stolee | 847a9e5 | 2021-04-01 01:49:39 +0000 | [diff] [blame] | 155 | static void show_other_files(struct index_state *istate, |
Brandon Williams | 23d6846 | 2017-06-12 15:14:01 -0700 | [diff] [blame] | 156 | const struct dir_struct *dir) |
Junio C Hamano | fcbc308 | 2005-11-06 17:26:31 -0800 | [diff] [blame] | 157 | { |
| 158 | int i; |
Linus Torvalds | 5698454 | 2007-04-14 16:22:08 -0700 | [diff] [blame] | 159 | |
Linus Torvalds | 453ec4b | 2006-05-16 19:02:14 -0700 | [diff] [blame] | 160 | for (i = 0; i < dir->nr; i++) { |
Linus Torvalds | 453ec4b | 2006-05-16 19:02:14 -0700 | [diff] [blame] | 161 | struct dir_entry *ent = dir->entries[i]; |
Brandon Williams | 23d6846 | 2017-06-12 15:14:01 -0700 | [diff] [blame] | 162 | if (!index_name_is_other(istate, ent->name, ent->len)) |
Jeff King | 98fa473 | 2008-10-16 11:07:26 -0400 | [diff] [blame] | 163 | continue; |
Nguyễn Thái Ngọc Duy | a52b321 | 2018-08-13 18:14:24 +0200 | [diff] [blame] | 164 | show_dir_entry(istate, tag_other, ent); |
Junio C Hamano | fcbc308 | 2005-11-06 17:26:31 -0800 | [diff] [blame] | 165 | } |
| 166 | } |
| 167 | |
Derrick Stolee | 847a9e5 | 2021-04-01 01:49:39 +0000 | [diff] [blame] | 168 | static void show_killed_files(struct index_state *istate, |
Brandon Williams | 23d6236 | 2017-06-12 15:14:00 -0700 | [diff] [blame] | 169 | const struct dir_struct *dir) |
Junio C Hamano | 6ca4594 | 2005-05-12 17:17:54 -0700 | [diff] [blame] | 170 | { |
| 171 | int i; |
Linus Torvalds | 453ec4b | 2006-05-16 19:02:14 -0700 | [diff] [blame] | 172 | for (i = 0; i < dir->nr; i++) { |
| 173 | struct dir_entry *ent = dir->entries[i]; |
Junio C Hamano | 6ca4594 | 2005-05-12 17:17:54 -0700 | [diff] [blame] | 174 | char *cp, *sp; |
| 175 | int pos, len, killed = 0; |
| 176 | |
| 177 | for (cp = ent->name; cp - ent->name < ent->len; cp = sp + 1) { |
| 178 | sp = strchr(cp, '/'); |
| 179 | if (!sp) { |
| 180 | /* If ent->name is prefix of an entry in the |
| 181 | * cache, it will be killed. |
| 182 | */ |
Brandon Williams | 23d6236 | 2017-06-12 15:14:00 -0700 | [diff] [blame] | 183 | pos = index_name_pos(istate, ent->name, ent->len); |
Junio C Hamano | 6ca4594 | 2005-05-12 17:17:54 -0700 | [diff] [blame] | 184 | if (0 <= pos) |
Johannes Schindelin | 033abf9 | 2018-05-02 11:38:39 +0200 | [diff] [blame] | 185 | BUG("killed-file %.*s not found", |
Johannes Schindelin | ef1177d1 | 2016-07-26 18:05:50 +0200 | [diff] [blame] | 186 | ent->len, ent->name); |
Junio C Hamano | 6ca4594 | 2005-05-12 17:17:54 -0700 | [diff] [blame] | 187 | pos = -pos - 1; |
Brandon Williams | 23d6236 | 2017-06-12 15:14:00 -0700 | [diff] [blame] | 188 | while (pos < istate->cache_nr && |
| 189 | ce_stage(istate->cache[pos])) |
Junio C Hamano | 6ca4594 | 2005-05-12 17:17:54 -0700 | [diff] [blame] | 190 | pos++; /* skip unmerged */ |
Brandon Williams | 23d6236 | 2017-06-12 15:14:00 -0700 | [diff] [blame] | 191 | if (istate->cache_nr <= pos) |
Junio C Hamano | 6ca4594 | 2005-05-12 17:17:54 -0700 | [diff] [blame] | 192 | break; |
| 193 | /* pos points at a name immediately after |
| 194 | * ent->name in the cache. Does it expect |
| 195 | * ent->name to be a directory? |
| 196 | */ |
Brandon Williams | 23d6236 | 2017-06-12 15:14:00 -0700 | [diff] [blame] | 197 | len = ce_namelen(istate->cache[pos]); |
Junio C Hamano | 6ca4594 | 2005-05-12 17:17:54 -0700 | [diff] [blame] | 198 | if ((ent->len < len) && |
Brandon Williams | 23d6236 | 2017-06-12 15:14:00 -0700 | [diff] [blame] | 199 | !strncmp(istate->cache[pos]->name, |
Junio C Hamano | 6ca4594 | 2005-05-12 17:17:54 -0700 | [diff] [blame] | 200 | ent->name, ent->len) && |
Brandon Williams | 23d6236 | 2017-06-12 15:14:00 -0700 | [diff] [blame] | 201 | istate->cache[pos]->name[ent->len] == '/') |
Junio C Hamano | 6ca4594 | 2005-05-12 17:17:54 -0700 | [diff] [blame] | 202 | killed = 1; |
| 203 | break; |
| 204 | } |
Brandon Williams | 23d6236 | 2017-06-12 15:14:00 -0700 | [diff] [blame] | 205 | if (0 <= index_name_pos(istate, ent->name, sp - ent->name)) { |
Junio C Hamano | 6ca4594 | 2005-05-12 17:17:54 -0700 | [diff] [blame] | 206 | /* If any of the leading directories in |
| 207 | * ent->name is registered in the cache, |
| 208 | * ent->name will be killed. |
| 209 | */ |
| 210 | killed = 1; |
| 211 | break; |
| 212 | } |
| 213 | } |
| 214 | if (killed) |
Nguyễn Thái Ngọc Duy | a52b321 | 2018-08-13 18:14:24 +0200 | [diff] [blame] | 215 | show_dir_entry(istate, tag_killed, dir->entries[i]); |
Junio C Hamano | 6ca4594 | 2005-05-12 17:17:54 -0700 | [diff] [blame] | 216 | } |
Linus Torvalds | 8695c8b | 2005-04-11 18:55:38 -0700 | [diff] [blame] | 217 | } |
| 218 | |
Brandon Williams | 188dce1 | 2017-06-22 11:43:48 -0700 | [diff] [blame] | 219 | static void show_files(struct repository *repo, struct dir_struct *dir); |
Brandon Williams | b2dfeb7 | 2017-03-17 10:22:57 -0700 | [diff] [blame] | 220 | |
Brandon Williams | 188dce1 | 2017-06-22 11:43:48 -0700 | [diff] [blame] | 221 | static void show_submodule(struct repository *superproject, |
| 222 | struct dir_struct *dir, const char *path) |
| 223 | { |
Stefan Beller | d5498e0 | 2018-11-28 16:27:53 -0800 | [diff] [blame] | 224 | struct repository subrepo; |
Brandon Williams | 188dce1 | 2017-06-22 11:43:48 -0700 | [diff] [blame] | 225 | |
Jonathan Tan | 8eb8dcf | 2021-09-09 11:47:28 -0700 | [diff] [blame] | 226 | if (repo_submodule_init(&subrepo, superproject, path, null_oid())) |
Brandon Williams | 188dce1 | 2017-06-22 11:43:48 -0700 | [diff] [blame] | 227 | return; |
| 228 | |
Stefan Beller | d5498e0 | 2018-11-28 16:27:53 -0800 | [diff] [blame] | 229 | if (repo_read_index(&subrepo) < 0) |
Brandon Williams | 188dce1 | 2017-06-22 11:43:48 -0700 | [diff] [blame] | 230 | die("index file corrupt"); |
| 231 | |
Stefan Beller | d5498e0 | 2018-11-28 16:27:53 -0800 | [diff] [blame] | 232 | show_files(&subrepo, dir); |
Brandon Williams | 188dce1 | 2017-06-22 11:43:48 -0700 | [diff] [blame] | 233 | |
Stefan Beller | d5498e0 | 2018-11-28 16:27:53 -0800 | [diff] [blame] | 234 | repo_clear(&subrepo); |
Brandon Williams | 07c01b9 | 2016-10-07 11:18:50 -0700 | [diff] [blame] | 235 | } |
| 236 | |
ZheNing Hu | ce74de9 | 2022-07-23 06:44:45 +0000 | [diff] [blame] | 237 | struct show_index_data { |
| 238 | const char *pathname; |
| 239 | struct index_state *istate; |
| 240 | const struct cache_entry *ce; |
| 241 | }; |
| 242 | |
| 243 | static size_t expand_show_index(struct strbuf *sb, const char *start, |
| 244 | void *context) |
| 245 | { |
| 246 | struct show_index_data *data = context; |
| 247 | const char *end; |
| 248 | const char *p; |
| 249 | size_t len = strbuf_expand_literal_cb(sb, start, NULL); |
| 250 | struct stat st; |
| 251 | |
| 252 | if (len) |
| 253 | return len; |
| 254 | if (*start != '(') |
| 255 | die(_("bad ls-files format: element '%s' " |
| 256 | "does not start with '('"), start); |
| 257 | |
| 258 | end = strchr(start + 1, ')'); |
| 259 | if (!end) |
ZheNing Hu | 746aae3 | 2022-09-11 14:03:17 +0000 | [diff] [blame] | 260 | die(_("bad ls-files format: element '%s' " |
ZheNing Hu | ce74de9 | 2022-07-23 06:44:45 +0000 | [diff] [blame] | 261 | "does not end in ')'"), start); |
| 262 | |
| 263 | len = end - start + 1; |
| 264 | if (skip_prefix(start, "(objectmode)", &p)) |
| 265 | strbuf_addf(sb, "%06o", data->ce->ce_mode); |
| 266 | else if (skip_prefix(start, "(objectname)", &p)) |
| 267 | strbuf_add_unique_abbrev(sb, &data->ce->oid, abbrev); |
| 268 | else if (skip_prefix(start, "(stage)", &p)) |
| 269 | strbuf_addf(sb, "%d", ce_stage(data->ce)); |
| 270 | else if (skip_prefix(start, "(eolinfo:index)", &p)) |
| 271 | strbuf_addstr(sb, S_ISREG(data->ce->ce_mode) ? |
| 272 | get_cached_convert_stats_ascii(data->istate, |
| 273 | data->ce->name) : ""); |
| 274 | else if (skip_prefix(start, "(eolinfo:worktree)", &p)) |
| 275 | strbuf_addstr(sb, !lstat(data->pathname, &st) && |
| 276 | S_ISREG(st.st_mode) ? |
| 277 | get_wt_convert_stats_ascii(data->pathname) : ""); |
| 278 | else if (skip_prefix(start, "(eolattr)", &p)) |
| 279 | strbuf_addstr(sb, get_convert_attr_ascii(data->istate, |
| 280 | data->pathname)); |
| 281 | else if (skip_prefix(start, "(path)", &p)) |
| 282 | write_name_to_buf(sb, data->pathname); |
| 283 | else |
| 284 | die(_("bad ls-files format: %%%.*s"), (int)len, start); |
| 285 | |
| 286 | return len; |
| 287 | } |
| 288 | |
| 289 | static void show_ce_fmt(struct repository *repo, const struct cache_entry *ce, |
| 290 | const char *format, const char *fullname) { |
| 291 | struct show_index_data data = { |
| 292 | .pathname = fullname, |
| 293 | .istate = repo->index, |
| 294 | .ce = ce, |
| 295 | }; |
| 296 | struct strbuf sb = STRBUF_INIT; |
| 297 | |
| 298 | strbuf_expand(&sb, format, expand_show_index, &data); |
| 299 | strbuf_addch(&sb, line_terminator); |
| 300 | fwrite(sb.buf, sb.len, 1, stdout); |
| 301 | strbuf_release(&sb); |
| 302 | } |
| 303 | |
Brandon Williams | 188dce1 | 2017-06-22 11:43:48 -0700 | [diff] [blame] | 304 | static void show_ce(struct repository *repo, struct dir_struct *dir, |
| 305 | const struct cache_entry *ce, const char *fullname, |
| 306 | const char *tag) |
Brandon Williams | e77aa33 | 2016-10-07 11:18:49 -0700 | [diff] [blame] | 307 | { |
Brandon Williams | 188dce1 | 2017-06-22 11:43:48 -0700 | [diff] [blame] | 308 | if (max_prefix_len > strlen(fullname)) |
Junio C Hamano | 7e44c93 | 2008-08-31 09:39:19 -0700 | [diff] [blame] | 309 | die("git ls-files: internal error - cache entry not superset of prefix"); |
Linus Torvalds | 5be4efb | 2005-08-21 12:55:33 -0700 | [diff] [blame] | 310 | |
Brandon Williams | 75a6315 | 2016-10-07 11:18:51 -0700 | [diff] [blame] | 311 | if (recurse_submodules && S_ISGITLINK(ce->ce_mode) && |
Brandon Williams | 188dce1 | 2017-06-22 11:43:48 -0700 | [diff] [blame] | 312 | is_submodule_active(repo, ce->name)) { |
| 313 | show_submodule(repo, dir, ce->name); |
Nguyễn Thái Ngọc Duy | a52b321 | 2018-08-13 18:14:24 +0200 | [diff] [blame] | 314 | } else if (match_pathspec(repo->index, &pathspec, fullname, strlen(fullname), |
Brandon Williams | 188dce1 | 2017-06-22 11:43:48 -0700 | [diff] [blame] | 315 | max_prefix_len, ps_matched, |
Brandon Williams | e77aa33 | 2016-10-07 11:18:49 -0700 | [diff] [blame] | 316 | S_ISDIR(ce->ce_mode) || |
| 317 | S_ISGITLINK(ce->ce_mode))) { |
ZheNing Hu | ce74de9 | 2022-07-23 06:44:45 +0000 | [diff] [blame] | 318 | if (format) { |
| 319 | show_ce_fmt(repo, ce, format, fullname); |
| 320 | print_debug(ce); |
| 321 | return; |
| 322 | } |
| 323 | |
Brandon Williams | a84f3e5 | 2017-06-12 15:14:08 -0700 | [diff] [blame] | 324 | tag = get_tag(ce, tag); |
Brandon Williams | e77aa33 | 2016-10-07 11:18:49 -0700 | [diff] [blame] | 325 | |
| 326 | if (!show_stage) { |
| 327 | fputs(tag, stdout); |
| 328 | } else { |
| 329 | printf("%s%06o %s %d\t", |
| 330 | tag, |
| 331 | ce->ce_mode, |
Jonathan Tan | 290eada | 2022-02-23 16:23:03 -0800 | [diff] [blame] | 332 | repo_find_unique_abbrev(repo, &ce->oid, abbrev), |
Brandon Williams | e77aa33 | 2016-10-07 11:18:49 -0700 | [diff] [blame] | 333 | ce_stage(ce)); |
| 334 | } |
Brandon Williams | 188dce1 | 2017-06-22 11:43:48 -0700 | [diff] [blame] | 335 | write_eolinfo(repo->index, ce, fullname); |
| 336 | write_name(fullname); |
Brandon Williams | 5306ccf | 2017-06-12 15:14:07 -0700 | [diff] [blame] | 337 | print_debug(ce); |
Junio C Hamano | 2bcab24 | 2006-02-08 21:50:18 -0800 | [diff] [blame] | 338 | } |
Linus Torvalds | 5be4efb | 2005-08-21 12:55:33 -0700 | [diff] [blame] | 339 | } |
| 340 | |
Derrick Stolee | 847a9e5 | 2021-04-01 01:49:39 +0000 | [diff] [blame] | 341 | static void show_ru_info(struct index_state *istate) |
Junio C Hamano | 9d9a2f4 | 2009-12-25 10:08:04 -0800 | [diff] [blame] | 342 | { |
Alex Riesen | 8a57c6e | 2010-07-03 14:41:54 +0200 | [diff] [blame] | 343 | struct string_list_item *item; |
| 344 | |
Brandon Williams | 2d407e2 | 2017-06-12 15:14:02 -0700 | [diff] [blame] | 345 | if (!istate->resolve_undo) |
Junio C Hamano | 9d9a2f4 | 2009-12-25 10:08:04 -0800 | [diff] [blame] | 346 | return; |
Alex Riesen | 8a57c6e | 2010-07-03 14:41:54 +0200 | [diff] [blame] | 347 | |
Brandon Williams | 2d407e2 | 2017-06-12 15:14:02 -0700 | [diff] [blame] | 348 | for_each_string_list_item(item, istate->resolve_undo) { |
Alex Riesen | 8a57c6e | 2010-07-03 14:41:54 +0200 | [diff] [blame] | 349 | const char *path = item->string; |
| 350 | struct resolve_undo_info *ui = item->util; |
| 351 | int i, len; |
| 352 | |
| 353 | len = strlen(path); |
| 354 | if (len < max_prefix_len) |
| 355 | continue; /* outside of the prefix */ |
Nguyễn Thái Ngọc Duy | a52b321 | 2018-08-13 18:14:24 +0200 | [diff] [blame] | 356 | if (!match_pathspec(istate, &pathspec, path, len, |
Nguyễn Thái Ngọc Duy | ae8d082 | 2014-01-24 20:40:33 +0700 | [diff] [blame] | 357 | max_prefix_len, ps_matched, 0)) |
Alex Riesen | 8a57c6e | 2010-07-03 14:41:54 +0200 | [diff] [blame] | 358 | continue; /* uninterested */ |
| 359 | for (i = 0; i < 3; i++) { |
| 360 | if (!ui->mode[i]) |
| 361 | continue; |
| 362 | printf("%s%06o %s %d\t", tag_resolve_undo, ui->mode[i], |
brian m. carlson | aab9583 | 2018-03-12 02:27:30 +0000 | [diff] [blame] | 363 | find_unique_abbrev(&ui->oid[i], abbrev), |
Alex Riesen | 8a57c6e | 2010-07-03 14:41:54 +0200 | [diff] [blame] | 364 | i + 1); |
Jiang Xin | e9a820c | 2013-06-25 23:53:46 +0800 | [diff] [blame] | 365 | write_name(path); |
Alex Riesen | 8a57c6e | 2010-07-03 14:41:54 +0200 | [diff] [blame] | 366 | } |
| 367 | } |
Junio C Hamano | 9d9a2f4 | 2009-12-25 10:08:04 -0800 | [diff] [blame] | 368 | } |
| 369 | |
Brandon Williams | 1d35e3b | 2017-06-12 15:14:03 -0700 | [diff] [blame] | 370 | static int ce_excluded(struct dir_struct *dir, struct index_state *istate, |
Brandon Williams | 188dce1 | 2017-06-22 11:43:48 -0700 | [diff] [blame] | 371 | const char *fullname, const struct cache_entry *ce) |
Junio C Hamano | 782cd4c | 2012-06-05 21:17:52 -0700 | [diff] [blame] | 372 | { |
| 373 | int dtype = ce_to_dtype(ce); |
Brandon Williams | 188dce1 | 2017-06-22 11:43:48 -0700 | [diff] [blame] | 374 | return is_excluded(dir, istate, fullname, &dtype); |
Junio C Hamano | 782cd4c | 2012-06-05 21:17:52 -0700 | [diff] [blame] | 375 | } |
| 376 | |
Brandon Williams | 188dce1 | 2017-06-22 11:43:48 -0700 | [diff] [blame] | 377 | static void construct_fullname(struct strbuf *out, const struct repository *repo, |
| 378 | const struct cache_entry *ce) |
| 379 | { |
| 380 | strbuf_reset(out); |
| 381 | if (repo->submodule_prefix) |
| 382 | strbuf_addstr(out, repo->submodule_prefix); |
| 383 | strbuf_addstr(out, ce->name); |
| 384 | } |
| 385 | |
| 386 | static void show_files(struct repository *repo, struct dir_struct *dir) |
Linus Torvalds | 8695c8b | 2005-04-11 18:55:38 -0700 | [diff] [blame] | 387 | { |
| 388 | int i; |
Brandon Williams | 188dce1 | 2017-06-22 11:43:48 -0700 | [diff] [blame] | 389 | struct strbuf fullname = STRBUF_INIT; |
Linus Torvalds | 8695c8b | 2005-04-11 18:55:38 -0700 | [diff] [blame] | 390 | |
| 391 | /* For cached/deleted files we don't need to even do the readdir */ |
Junio C Hamano | 6ca4594 | 2005-05-12 17:17:54 -0700 | [diff] [blame] | 392 | if (show_others || show_killed) { |
Junio C Hamano | 2eac2a4 | 2013-08-15 12:13:46 -0700 | [diff] [blame] | 393 | if (!show_others) |
| 394 | dir->flags |= DIR_COLLECT_KILLED_ONLY; |
Brandon Williams | 188dce1 | 2017-06-22 11:43:48 -0700 | [diff] [blame] | 395 | fill_directory(dir, repo->index, &pathspec); |
Junio C Hamano | 6ca4594 | 2005-05-12 17:17:54 -0700 | [diff] [blame] | 396 | if (show_others) |
Brandon Williams | 188dce1 | 2017-06-22 11:43:48 -0700 | [diff] [blame] | 397 | show_other_files(repo->index, dir); |
Junio C Hamano | 6ca4594 | 2005-05-12 17:17:54 -0700 | [diff] [blame] | 398 | if (show_killed) |
Brandon Williams | 188dce1 | 2017-06-22 11:43:48 -0700 | [diff] [blame] | 399 | show_killed_files(repo->index, dir); |
Linus Torvalds | 8695c8b | 2005-04-11 18:55:38 -0700 | [diff] [blame] | 400 | } |
Brandon Williams | 188dce1 | 2017-06-22 11:43:48 -0700 | [diff] [blame] | 401 | |
ZheNing Hu | ed644d1 | 2021-01-23 10:20:09 +0000 | [diff] [blame] | 402 | if (!(show_cached || show_stage || show_deleted || show_modified)) |
| 403 | return; |
Derrick Stolee | 7808709 | 2021-12-22 14:20:53 +0000 | [diff] [blame] | 404 | |
| 405 | if (!show_sparse_dirs) |
| 406 | ensure_full_index(repo->index); |
| 407 | |
ZheNing Hu | ed644d1 | 2021-01-23 10:20:09 +0000 | [diff] [blame] | 408 | for (i = 0; i < repo->index->cache_nr; i++) { |
| 409 | const struct cache_entry *ce = repo->index->cache[i]; |
| 410 | struct stat st; |
| 411 | int stat_err; |
Brandon Williams | 188dce1 | 2017-06-22 11:43:48 -0700 | [diff] [blame] | 412 | |
ZheNing Hu | ed644d1 | 2021-01-23 10:20:09 +0000 | [diff] [blame] | 413 | construct_fullname(&fullname, repo, ce); |
| 414 | |
| 415 | if ((dir->flags & DIR_SHOW_IGNORED) && |
| 416 | !ce_excluded(dir, repo->index, fullname.buf, ce)) |
| 417 | continue; |
| 418 | if (ce->ce_flags & CE_UPDATE) |
| 419 | continue; |
| 420 | if ((show_cached || show_stage) && |
ZheNing Hu | 93a7d98 | 2021-01-23 10:20:10 +0000 | [diff] [blame] | 421 | (!show_unmerged || ce_stage(ce))) { |
Brandon Williams | 188dce1 | 2017-06-22 11:43:48 -0700 | [diff] [blame] | 422 | show_ce(repo, dir, ce, fullname.buf, |
| 423 | ce_stage(ce) ? tag_unmerged : |
| 424 | (ce_skip_worktree(ce) ? tag_skip_worktree : |
| 425 | tag_cached)); |
ZheNing Hu | 93a7d98 | 2021-01-23 10:20:10 +0000 | [diff] [blame] | 426 | if (skipping_duplicates) |
| 427 | goto skip_to_next_name; |
| 428 | } |
Brandon Williams | 188dce1 | 2017-06-22 11:43:48 -0700 | [diff] [blame] | 429 | |
ZheNing Hu | ed644d1 | 2021-01-23 10:20:09 +0000 | [diff] [blame] | 430 | if (!(show_deleted || show_modified)) |
| 431 | continue; |
| 432 | if (ce_skip_worktree(ce)) |
| 433 | continue; |
| 434 | stat_err = lstat(fullname.buf, &st); |
| 435 | if (stat_err && (errno != ENOENT && errno != ENOTDIR)) |
| 436 | error_errno("cannot lstat '%s'", fullname.buf); |
ZheNing Hu | 93a7d98 | 2021-01-23 10:20:10 +0000 | [diff] [blame] | 437 | if (stat_err && show_deleted) { |
ZheNing Hu | ed644d1 | 2021-01-23 10:20:09 +0000 | [diff] [blame] | 438 | show_ce(repo, dir, ce, fullname.buf, tag_removed); |
ZheNing Hu | 93a7d98 | 2021-01-23 10:20:10 +0000 | [diff] [blame] | 439 | if (skipping_duplicates) |
| 440 | goto skip_to_next_name; |
| 441 | } |
ZheNing Hu | ed644d1 | 2021-01-23 10:20:09 +0000 | [diff] [blame] | 442 | if (show_modified && |
ZheNing Hu | 93a7d98 | 2021-01-23 10:20:10 +0000 | [diff] [blame] | 443 | (stat_err || ie_modified(repo->index, ce, &st, 0))) { |
ZheNing Hu | ed644d1 | 2021-01-23 10:20:09 +0000 | [diff] [blame] | 444 | show_ce(repo, dir, ce, fullname.buf, tag_modified); |
ZheNing Hu | 93a7d98 | 2021-01-23 10:20:10 +0000 | [diff] [blame] | 445 | if (skipping_duplicates) |
| 446 | goto skip_to_next_name; |
| 447 | } |
| 448 | continue; |
| 449 | |
| 450 | skip_to_next_name: |
| 451 | { |
| 452 | int j; |
| 453 | struct cache_entry **cache = repo->index->cache; |
| 454 | for (j = i + 1; j < repo->index->cache_nr; j++) |
| 455 | if (strcmp(ce->name, cache[j]->name)) |
| 456 | break; |
| 457 | i = j - 1; /* compensate for the for loop */ |
| 458 | } |
Linus Torvalds | 8695c8b | 2005-04-11 18:55:38 -0700 | [diff] [blame] | 459 | } |
Brandon Williams | 188dce1 | 2017-06-22 11:43:48 -0700 | [diff] [blame] | 460 | |
| 461 | strbuf_release(&fullname); |
Linus Torvalds | 8695c8b | 2005-04-11 18:55:38 -0700 | [diff] [blame] | 462 | } |
| 463 | |
Linus Torvalds | 5be4efb | 2005-08-21 12:55:33 -0700 | [diff] [blame] | 464 | /* |
| 465 | * Prune the index to only contain stuff starting with "prefix" |
| 466 | */ |
Brandon Williams | 6510ae1 | 2017-06-12 15:14:04 -0700 | [diff] [blame] | 467 | static void prune_index(struct index_state *istate, |
| 468 | const char *prefix, size_t prefixlen) |
Linus Torvalds | 5be4efb | 2005-08-21 12:55:33 -0700 | [diff] [blame] | 469 | { |
René Scharfe | 7b4158a | 2017-02-10 20:42:28 +0100 | [diff] [blame] | 470 | int pos; |
Linus Torvalds | 5be4efb | 2005-08-21 12:55:33 -0700 | [diff] [blame] | 471 | unsigned int first, last; |
| 472 | |
René Scharfe | 168e635 | 2017-07-16 13:16:01 +0200 | [diff] [blame] | 473 | if (!prefix || !istate->cache_nr) |
René Scharfe | 7b4158a | 2017-02-10 20:42:28 +0100 | [diff] [blame] | 474 | return; |
Brandon Williams | 6510ae1 | 2017-06-12 15:14:04 -0700 | [diff] [blame] | 475 | pos = index_name_pos(istate, prefix, prefixlen); |
Linus Torvalds | 5be4efb | 2005-08-21 12:55:33 -0700 | [diff] [blame] | 476 | if (pos < 0) |
| 477 | pos = -pos-1; |
René Scharfe | 96f6d3f | 2017-02-10 21:03:30 +0100 | [diff] [blame] | 478 | first = pos; |
Brandon Williams | 6510ae1 | 2017-06-12 15:14:04 -0700 | [diff] [blame] | 479 | last = istate->cache_nr; |
Linus Torvalds | 5be4efb | 2005-08-21 12:55:33 -0700 | [diff] [blame] | 480 | while (last > first) { |
René Scharfe | 568a05c | 2019-06-13 19:51:56 +0200 | [diff] [blame] | 481 | int next = first + ((last - first) >> 1); |
Brandon Williams | 6510ae1 | 2017-06-12 15:14:04 -0700 | [diff] [blame] | 482 | const struct cache_entry *ce = istate->cache[next]; |
René Scharfe | 7b4158a | 2017-02-10 20:42:28 +0100 | [diff] [blame] | 483 | if (!strncmp(ce->name, prefix, prefixlen)) { |
Linus Torvalds | 5be4efb | 2005-08-21 12:55:33 -0700 | [diff] [blame] | 484 | first = next+1; |
| 485 | continue; |
| 486 | } |
| 487 | last = next; |
| 488 | } |
René Scharfe | f331ab9 | 2017-07-15 22:00:45 +0200 | [diff] [blame] | 489 | MOVE_ARRAY(istate->cache, istate->cache + pos, last - pos); |
Brandon Williams | 6510ae1 | 2017-06-12 15:14:04 -0700 | [diff] [blame] | 490 | istate->cache_nr = last - pos; |
Linus Torvalds | 5be4efb | 2005-08-21 12:55:33 -0700 | [diff] [blame] | 491 | } |
| 492 | |
Brandon Williams | cbca060 | 2017-05-11 15:04:25 -0700 | [diff] [blame] | 493 | static int get_common_prefix_len(const char *common_prefix) |
| 494 | { |
| 495 | int common_prefix_len; |
| 496 | |
| 497 | if (!common_prefix) |
| 498 | return 0; |
| 499 | |
| 500 | common_prefix_len = strlen(common_prefix); |
| 501 | |
| 502 | /* |
| 503 | * If the prefix has a trailing slash, strip it so that submodules wont |
| 504 | * be pruned from the index. |
| 505 | */ |
| 506 | if (common_prefix[common_prefix_len - 1] == '/') |
| 507 | common_prefix_len--; |
| 508 | |
| 509 | return common_prefix_len; |
| 510 | } |
| 511 | |
Ævar Arnfjörð Bjarmason | eefadd1 | 2021-03-20 23:37:46 +0100 | [diff] [blame] | 512 | static int read_one_entry_opt(struct index_state *istate, |
| 513 | const struct object_id *oid, |
Ævar Arnfjörð Bjarmason | 9614ad3 | 2021-03-20 23:37:48 +0100 | [diff] [blame] | 514 | struct strbuf *base, |
Ævar Arnfjörð Bjarmason | eefadd1 | 2021-03-20 23:37:46 +0100 | [diff] [blame] | 515 | const char *pathname, |
Ævar Arnfjörð Bjarmason | fcc7c12 | 2021-03-20 23:37:47 +0100 | [diff] [blame] | 516 | unsigned mode, int opt) |
Ævar Arnfjörð Bjarmason | eefadd1 | 2021-03-20 23:37:46 +0100 | [diff] [blame] | 517 | { |
| 518 | int len; |
| 519 | struct cache_entry *ce; |
| 520 | |
| 521 | if (S_ISDIR(mode)) |
| 522 | return READ_TREE_RECURSIVE; |
| 523 | |
| 524 | len = strlen(pathname); |
Ævar Arnfjörð Bjarmason | 9614ad3 | 2021-03-20 23:37:48 +0100 | [diff] [blame] | 525 | ce = make_empty_cache_entry(istate, base->len + len); |
Ævar Arnfjörð Bjarmason | eefadd1 | 2021-03-20 23:37:46 +0100 | [diff] [blame] | 526 | |
| 527 | ce->ce_mode = create_ce_mode(mode); |
Ævar Arnfjörð Bjarmason | fcc7c12 | 2021-03-20 23:37:47 +0100 | [diff] [blame] | 528 | ce->ce_flags = create_ce_flags(1); |
Ævar Arnfjörð Bjarmason | 9614ad3 | 2021-03-20 23:37:48 +0100 | [diff] [blame] | 529 | ce->ce_namelen = base->len + len; |
| 530 | memcpy(ce->name, base->buf, base->len); |
| 531 | memcpy(ce->name + base->len, pathname, len+1); |
Ævar Arnfjörð Bjarmason | eefadd1 | 2021-03-20 23:37:46 +0100 | [diff] [blame] | 532 | oidcpy(&ce->oid, oid); |
| 533 | return add_index_entry(istate, ce, opt); |
| 534 | } |
| 535 | |
| 536 | static int read_one_entry(const struct object_id *oid, struct strbuf *base, |
Ævar Arnfjörð Bjarmason | 4795748 | 2021-03-20 23:37:51 +0100 | [diff] [blame] | 537 | const char *pathname, unsigned mode, |
Ævar Arnfjörð Bjarmason | eefadd1 | 2021-03-20 23:37:46 +0100 | [diff] [blame] | 538 | void *context) |
| 539 | { |
| 540 | struct index_state *istate = context; |
Ævar Arnfjörð Bjarmason | 9614ad3 | 2021-03-20 23:37:48 +0100 | [diff] [blame] | 541 | return read_one_entry_opt(istate, oid, base, pathname, |
Ævar Arnfjörð Bjarmason | fcc7c12 | 2021-03-20 23:37:47 +0100 | [diff] [blame] | 542 | mode, |
Ævar Arnfjörð Bjarmason | eefadd1 | 2021-03-20 23:37:46 +0100 | [diff] [blame] | 543 | ADD_CACHE_OK_TO_ADD|ADD_CACHE_SKIP_DFCHECK); |
| 544 | } |
| 545 | |
| 546 | /* |
| 547 | * This is used when the caller knows there is no existing entries at |
| 548 | * the stage that will conflict with the entry being added. |
| 549 | */ |
| 550 | static int read_one_entry_quick(const struct object_id *oid, struct strbuf *base, |
Ævar Arnfjörð Bjarmason | 4795748 | 2021-03-20 23:37:51 +0100 | [diff] [blame] | 551 | const char *pathname, unsigned mode, |
Ævar Arnfjörð Bjarmason | eefadd1 | 2021-03-20 23:37:46 +0100 | [diff] [blame] | 552 | void *context) |
| 553 | { |
| 554 | struct index_state *istate = context; |
Ævar Arnfjörð Bjarmason | 9614ad3 | 2021-03-20 23:37:48 +0100 | [diff] [blame] | 555 | return read_one_entry_opt(istate, oid, base, pathname, |
| 556 | mode, ADD_CACHE_JUST_APPEND); |
Ævar Arnfjörð Bjarmason | eefadd1 | 2021-03-20 23:37:46 +0100 | [diff] [blame] | 557 | } |
| 558 | |
Junio C Hamano | 64586e7 | 2007-09-12 16:04:22 -0700 | [diff] [blame] | 559 | /* |
| 560 | * Read the tree specified with --with-tree option |
| 561 | * (typically, HEAD) into stage #1 and then |
| 562 | * squash them down to stage #0. This is used for |
| 563 | * --error-unmatch to list and check the path patterns |
| 564 | * that were given from the command line. We are not |
| 565 | * going to write this index out. |
| 566 | */ |
Brandon Williams | 312c984 | 2017-06-12 15:13:58 -0700 | [diff] [blame] | 567 | void overlay_tree_on_index(struct index_state *istate, |
| 568 | const char *tree_name, const char *prefix) |
Junio C Hamano | 64586e7 | 2007-09-12 16:04:22 -0700 | [diff] [blame] | 569 | { |
| 570 | struct tree *tree; |
brian m. carlson | 6f37eb7 | 2017-05-06 22:10:31 +0000 | [diff] [blame] | 571 | struct object_id oid; |
Nguyễn Thái Ngọc Duy | f0096c0 | 2011-03-25 16:34:19 +0700 | [diff] [blame] | 572 | struct pathspec pathspec; |
Junio C Hamano | 64586e7 | 2007-09-12 16:04:22 -0700 | [diff] [blame] | 573 | struct cache_entry *last_stage0 = NULL; |
| 574 | int i; |
Ævar Arnfjörð Bjarmason | 9614ad3 | 2021-03-20 23:37:48 +0100 | [diff] [blame] | 575 | read_tree_fn_t fn = NULL; |
| 576 | int err; |
Junio C Hamano | 64586e7 | 2007-09-12 16:04:22 -0700 | [diff] [blame] | 577 | |
brian m. carlson | 6f37eb7 | 2017-05-06 22:10:31 +0000 | [diff] [blame] | 578 | if (get_oid(tree_name, &oid)) |
Junio C Hamano | 64586e7 | 2007-09-12 16:04:22 -0700 | [diff] [blame] | 579 | die("tree-ish %s not found.", tree_name); |
brian m. carlson | a9dbc17 | 2017-05-06 22:10:37 +0000 | [diff] [blame] | 580 | tree = parse_tree_indirect(&oid); |
Junio C Hamano | 64586e7 | 2007-09-12 16:04:22 -0700 | [diff] [blame] | 581 | if (!tree) |
| 582 | die("bad tree-ish %s", tree_name); |
| 583 | |
| 584 | /* Hoist the unmerged entries up to stage #3 to make room */ |
Derrick Stolee | 42f44e8 | 2021-04-01 01:49:49 +0000 | [diff] [blame] | 585 | /* TODO: audit for interaction with sparse-index. */ |
| 586 | ensure_full_index(istate); |
Brandon Williams | 312c984 | 2017-06-12 15:13:58 -0700 | [diff] [blame] | 587 | for (i = 0; i < istate->cache_nr; i++) { |
| 588 | struct cache_entry *ce = istate->cache[i]; |
Junio C Hamano | 64586e7 | 2007-09-12 16:04:22 -0700 | [diff] [blame] | 589 | if (!ce_stage(ce)) |
| 590 | continue; |
Linus Torvalds | 7a51ed6 | 2008-01-14 16:03:17 -0800 | [diff] [blame] | 591 | ce->ce_flags |= CE_STAGEMASK; |
Junio C Hamano | 64586e7 | 2007-09-12 16:04:22 -0700 | [diff] [blame] | 592 | } |
| 593 | |
| 594 | if (prefix) { |
Nguyễn Thái Ngọc Duy | 9a08727 | 2013-07-14 15:35:59 +0700 | [diff] [blame] | 595 | static const char *(matchbuf[1]); |
| 596 | matchbuf[0] = NULL; |
| 597 | parse_pathspec(&pathspec, PATHSPEC_ALL_MAGIC, |
| 598 | PATHSPEC_PREFER_CWD, prefix, matchbuf); |
Junio C Hamano | 64586e7 | 2007-09-12 16:04:22 -0700 | [diff] [blame] | 599 | } else |
Nguyễn Thái Ngọc Duy | 9a08727 | 2013-07-14 15:35:59 +0700 | [diff] [blame] | 600 | memset(&pathspec, 0, sizeof(pathspec)); |
Ævar Arnfjörð Bjarmason | 9614ad3 | 2021-03-20 23:37:48 +0100 | [diff] [blame] | 601 | |
| 602 | /* |
| 603 | * See if we have cache entry at the stage. If so, |
| 604 | * do it the original slow way, otherwise, append and then |
| 605 | * sort at the end. |
| 606 | */ |
| 607 | for (i = 0; !fn && i < istate->cache_nr; i++) { |
| 608 | const struct cache_entry *ce = istate->cache[i]; |
| 609 | if (ce_stage(ce) == 1) |
| 610 | fn = read_one_entry; |
| 611 | } |
| 612 | |
| 613 | if (!fn) |
| 614 | fn = read_one_entry_quick; |
Ævar Arnfjörð Bjarmason | 4795748 | 2021-03-20 23:37:51 +0100 | [diff] [blame] | 615 | err = read_tree(the_repository, tree, &pathspec, fn, istate); |
Ævar Arnfjörð Bjarmason | 9614ad3 | 2021-03-20 23:37:48 +0100 | [diff] [blame] | 616 | if (err) |
Junio C Hamano | 64586e7 | 2007-09-12 16:04:22 -0700 | [diff] [blame] | 617 | die("unable to read tree entries %s", tree_name); |
| 618 | |
Ævar Arnfjörð Bjarmason | 9614ad3 | 2021-03-20 23:37:48 +0100 | [diff] [blame] | 619 | /* |
| 620 | * Sort the cache entry -- we need to nuke the cache tree, though. |
| 621 | */ |
| 622 | if (fn == read_one_entry_quick) { |
| 623 | cache_tree_free(&istate->cache_tree); |
| 624 | QSORT(istate->cache, istate->cache_nr, cmp_cache_name_compare); |
| 625 | } |
| 626 | |
Brandon Williams | 312c984 | 2017-06-12 15:13:58 -0700 | [diff] [blame] | 627 | for (i = 0; i < istate->cache_nr; i++) { |
| 628 | struct cache_entry *ce = istate->cache[i]; |
Junio C Hamano | 64586e7 | 2007-09-12 16:04:22 -0700 | [diff] [blame] | 629 | switch (ce_stage(ce)) { |
| 630 | case 0: |
| 631 | last_stage0 = ce; |
| 632 | /* fallthru */ |
| 633 | default: |
| 634 | continue; |
| 635 | case 1: |
| 636 | /* |
| 637 | * If there is stage #0 entry for this, we do not |
| 638 | * need to show it. We use CE_UPDATE bit to mark |
| 639 | * such an entry. |
| 640 | */ |
| 641 | if (last_stage0 && |
| 642 | !strcmp(last_stage0->name, ce->name)) |
Linus Torvalds | 7a51ed6 | 2008-01-14 16:03:17 -0800 | [diff] [blame] | 643 | ce->ce_flags |= CE_UPDATE; |
Junio C Hamano | 64586e7 | 2007-09-12 16:04:22 -0700 | [diff] [blame] | 644 | } |
| 645 | } |
| 646 | } |
| 647 | |
Miklos Vajna | ce8e880 | 2009-02-17 15:27:11 +0100 | [diff] [blame] | 648 | static const char * const ls_files_usage[] = { |
Alex Henrie | 9c9b4f2 | 2015-01-13 00:44:47 -0700 | [diff] [blame] | 649 | N_("git ls-files [<options>] [<file>...]"), |
Miklos Vajna | ce8e880 | 2009-02-17 15:27:11 +0100 | [diff] [blame] | 650 | NULL |
| 651 | }; |
| 652 | |
Miklos Vajna | ce8e880 | 2009-02-17 15:27:11 +0100 | [diff] [blame] | 653 | static int option_parse_exclude(const struct option *opt, |
| 654 | const char *arg, int unset) |
| 655 | { |
Adam Spiers | 72aeb18 | 2013-01-16 13:25:58 +0000 | [diff] [blame] | 656 | struct string_list *exclude_list = opt->value; |
Miklos Vajna | ce8e880 | 2009-02-17 15:27:11 +0100 | [diff] [blame] | 657 | |
Jeff King | 517fe80 | 2018-11-05 01:45:42 -0500 | [diff] [blame] | 658 | BUG_ON_OPT_NEG(unset); |
| 659 | |
Miklos Vajna | ce8e880 | 2009-02-17 15:27:11 +0100 | [diff] [blame] | 660 | exc_given = 1; |
Adam Spiers | 72aeb18 | 2013-01-16 13:25:58 +0000 | [diff] [blame] | 661 | string_list_append(exclude_list, arg); |
Miklos Vajna | ce8e880 | 2009-02-17 15:27:11 +0100 | [diff] [blame] | 662 | |
| 663 | return 0; |
| 664 | } |
| 665 | |
| 666 | static int option_parse_exclude_from(const struct option *opt, |
| 667 | const char *arg, int unset) |
| 668 | { |
| 669 | struct dir_struct *dir = opt->value; |
| 670 | |
Jeff King | 517fe80 | 2018-11-05 01:45:42 -0500 | [diff] [blame] | 671 | BUG_ON_OPT_NEG(unset); |
| 672 | |
Miklos Vajna | ce8e880 | 2009-02-17 15:27:11 +0100 | [diff] [blame] | 673 | exc_given = 1; |
Derrick Stolee | 65edd96 | 2019-09-03 11:04:57 -0700 | [diff] [blame] | 674 | add_patterns_from_file(dir, arg); |
Miklos Vajna | ce8e880 | 2009-02-17 15:27:11 +0100 | [diff] [blame] | 675 | |
| 676 | return 0; |
| 677 | } |
| 678 | |
| 679 | static int option_parse_exclude_standard(const struct option *opt, |
| 680 | const char *arg, int unset) |
| 681 | { |
| 682 | struct dir_struct *dir = opt->value; |
| 683 | |
Jeff King | 517fe80 | 2018-11-05 01:45:42 -0500 | [diff] [blame] | 684 | BUG_ON_OPT_NEG(unset); |
| 685 | BUG_ON_OPT_ARG(arg); |
| 686 | |
Miklos Vajna | ce8e880 | 2009-02-17 15:27:11 +0100 | [diff] [blame] | 687 | exc_given = 1; |
| 688 | setup_standard_excludes(dir); |
| 689 | |
| 690 | return 0; |
| 691 | } |
Nicolas Pitre | cf9a113 | 2005-04-28 15:06:25 -0700 | [diff] [blame] | 692 | |
Clemens Buchacher | efad1a5 | 2010-06-03 15:39:18 +0200 | [diff] [blame] | 693 | int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix) |
Linus Torvalds | 8695c8b | 2005-04-11 18:55:38 -0700 | [diff] [blame] | 694 | { |
Adam Spiers | 72aeb18 | 2013-01-16 13:25:58 +0000 | [diff] [blame] | 695 | int require_work_tree = 0, show_tag = 0, i; |
Andrzej Hunt | 4c217a4 | 2021-04-25 14:16:10 +0000 | [diff] [blame] | 696 | char *max_prefix; |
Ævar Arnfjörð Bjarmason | ce93a4c | 2021-07-01 12:51:27 +0200 | [diff] [blame] | 697 | struct dir_struct dir = DIR_INIT; |
Derrick Stolee | caa3d55 | 2019-09-03 11:04:56 -0700 | [diff] [blame] | 698 | struct pattern_list *pl; |
Adam Spiers | 72aeb18 | 2013-01-16 13:25:58 +0000 | [diff] [blame] | 699 | struct string_list exclude_list = STRING_LIST_INIT_NODUP; |
Miklos Vajna | ce8e880 | 2009-02-17 15:27:11 +0100 | [diff] [blame] | 700 | struct option builtin_ls_files_options[] = { |
Jeff King | 1f3c79a | 2016-01-31 06:35:46 -0500 | [diff] [blame] | 701 | /* Think twice before adding "--nul" synonym to this */ |
| 702 | OPT_SET_INT('z', NULL, &line_terminator, |
Bagas Sanjaya | 54b4d12 | 2021-09-21 18:13:05 +0700 | [diff] [blame] | 703 | N_("separate paths with the NUL character"), '\0'), |
Stefan Beller | d5d09d4 | 2013-08-03 13:51:19 +0200 | [diff] [blame] | 704 | OPT_BOOL('t', NULL, &show_tag, |
Nguyễn Thái Ngọc Duy | 377adc3 | 2012-08-20 19:32:20 +0700 | [diff] [blame] | 705 | N_("identify the file status with tags")), |
Stefan Beller | d5d09d4 | 2013-08-03 13:51:19 +0200 | [diff] [blame] | 706 | OPT_BOOL('v', NULL, &show_valid_bit, |
Nguyễn Thái Ngọc Duy | 377adc3 | 2012-08-20 19:32:20 +0700 | [diff] [blame] | 707 | N_("use lowercase letters for 'assume unchanged' files")), |
Ben Peart | d8c71db | 2017-09-22 12:35:42 -0400 | [diff] [blame] | 708 | OPT_BOOL('f', NULL, &show_fsmonitor_bit, |
| 709 | N_("use lowercase letters for 'fsmonitor clean' files")), |
Stefan Beller | d5d09d4 | 2013-08-03 13:51:19 +0200 | [diff] [blame] | 710 | OPT_BOOL('c', "cached", &show_cached, |
Nguyễn Thái Ngọc Duy | 377adc3 | 2012-08-20 19:32:20 +0700 | [diff] [blame] | 711 | N_("show cached files in the output (default)")), |
Stefan Beller | d5d09d4 | 2013-08-03 13:51:19 +0200 | [diff] [blame] | 712 | OPT_BOOL('d', "deleted", &show_deleted, |
Nguyễn Thái Ngọc Duy | 377adc3 | 2012-08-20 19:32:20 +0700 | [diff] [blame] | 713 | N_("show deleted files in the output")), |
Stefan Beller | d5d09d4 | 2013-08-03 13:51:19 +0200 | [diff] [blame] | 714 | OPT_BOOL('m', "modified", &show_modified, |
Nguyễn Thái Ngọc Duy | 377adc3 | 2012-08-20 19:32:20 +0700 | [diff] [blame] | 715 | N_("show modified files in the output")), |
Stefan Beller | d5d09d4 | 2013-08-03 13:51:19 +0200 | [diff] [blame] | 716 | OPT_BOOL('o', "others", &show_others, |
Nguyễn Thái Ngọc Duy | 377adc3 | 2012-08-20 19:32:20 +0700 | [diff] [blame] | 717 | N_("show other files in the output")), |
Miklos Vajna | ce8e880 | 2009-02-17 15:27:11 +0100 | [diff] [blame] | 718 | OPT_BIT('i', "ignored", &dir.flags, |
Nguyễn Thái Ngọc Duy | 377adc3 | 2012-08-20 19:32:20 +0700 | [diff] [blame] | 719 | N_("show ignored files in the output"), |
Miklos Vajna | ce8e880 | 2009-02-17 15:27:11 +0100 | [diff] [blame] | 720 | DIR_SHOW_IGNORED), |
Stefan Beller | d5d09d4 | 2013-08-03 13:51:19 +0200 | [diff] [blame] | 721 | OPT_BOOL('s', "stage", &show_stage, |
Nguyễn Thái Ngọc Duy | 377adc3 | 2012-08-20 19:32:20 +0700 | [diff] [blame] | 722 | N_("show staged contents' object name in the output")), |
Stefan Beller | d5d09d4 | 2013-08-03 13:51:19 +0200 | [diff] [blame] | 723 | OPT_BOOL('k', "killed", &show_killed, |
Nguyễn Thái Ngọc Duy | 377adc3 | 2012-08-20 19:32:20 +0700 | [diff] [blame] | 724 | N_("show files on the filesystem that need to be removed")), |
Miklos Vajna | ce8e880 | 2009-02-17 15:27:11 +0100 | [diff] [blame] | 725 | OPT_BIT(0, "directory", &dir.flags, |
Alex Henrie | ad5fe37 | 2014-08-30 13:56:01 -0600 | [diff] [blame] | 726 | N_("show 'other' directories' names only"), |
Miklos Vajna | ce8e880 | 2009-02-17 15:27:11 +0100 | [diff] [blame] | 727 | DIR_SHOW_OTHER_DIRECTORIES), |
Torsten Bögershausen | a7630bd | 2016-01-16 07:50:02 +0100 | [diff] [blame] | 728 | OPT_BOOL(0, "eol", &show_eol, N_("show line endings of files")), |
Jeff King | e9008b9 | 2009-05-08 01:01:17 -0400 | [diff] [blame] | 729 | OPT_NEGBIT(0, "empty-directory", &dir.flags, |
Nguyễn Thái Ngọc Duy | 377adc3 | 2012-08-20 19:32:20 +0700 | [diff] [blame] | 730 | N_("don't show empty directories"), |
Miklos Vajna | ce8e880 | 2009-02-17 15:27:11 +0100 | [diff] [blame] | 731 | DIR_HIDE_EMPTY_DIRECTORIES), |
Stefan Beller | d5d09d4 | 2013-08-03 13:51:19 +0200 | [diff] [blame] | 732 | OPT_BOOL('u', "unmerged", &show_unmerged, |
Nguyễn Thái Ngọc Duy | 377adc3 | 2012-08-20 19:32:20 +0700 | [diff] [blame] | 733 | N_("show unmerged files in the output")), |
Stefan Beller | d5d09d4 | 2013-08-03 13:51:19 +0200 | [diff] [blame] | 734 | OPT_BOOL(0, "resolve-undo", &show_resolve_undo, |
Nguyễn Thái Ngọc Duy | 377adc3 | 2012-08-20 19:32:20 +0700 | [diff] [blame] | 735 | N_("show resolve-undo information")), |
Denton Liu | 203c853 | 2020-04-28 04:36:28 -0400 | [diff] [blame] | 736 | OPT_CALLBACK_F('x', "exclude", &exclude_list, N_("pattern"), |
Nguyễn Thái Ngọc Duy | 377adc3 | 2012-08-20 19:32:20 +0700 | [diff] [blame] | 737 | N_("skip files matching pattern"), |
Denton Liu | 203c853 | 2020-04-28 04:36:28 -0400 | [diff] [blame] | 738 | PARSE_OPT_NONEG, option_parse_exclude), |
| 739 | OPT_CALLBACK_F('X', "exclude-from", &dir, N_("file"), |
Bagas Sanjaya | 54b4d12 | 2021-09-21 18:13:05 +0700 | [diff] [blame] | 740 | N_("read exclude patterns from <file>"), |
Denton Liu | 203c853 | 2020-04-28 04:36:28 -0400 | [diff] [blame] | 741 | PARSE_OPT_NONEG, option_parse_exclude_from), |
Nguyễn Thái Ngọc Duy | 377adc3 | 2012-08-20 19:32:20 +0700 | [diff] [blame] | 742 | OPT_STRING(0, "exclude-per-directory", &dir.exclude_per_dir, N_("file"), |
| 743 | N_("read additional per-directory exclude patterns in <file>")), |
Denton Liu | 203c853 | 2020-04-28 04:36:28 -0400 | [diff] [blame] | 744 | OPT_CALLBACK_F(0, "exclude-standard", &dir, NULL, |
Nguyễn Thái Ngọc Duy | 377adc3 | 2012-08-20 19:32:20 +0700 | [diff] [blame] | 745 | N_("add the standard git exclusions"), |
Jeff King | ccf659e | 2018-11-05 01:39:20 -0500 | [diff] [blame] | 746 | PARSE_OPT_NOARG | PARSE_OPT_NONEG, |
Denton Liu | 203c853 | 2020-04-28 04:36:28 -0400 | [diff] [blame] | 747 | option_parse_exclude_standard), |
Nguyễn Thái Ngọc Duy | 3e4a67b | 2018-05-20 17:42:58 +0200 | [diff] [blame] | 748 | OPT_SET_INT_F(0, "full-name", &prefix_len, |
| 749 | N_("make the output relative to the project top directory"), |
| 750 | 0, PARSE_OPT_NONEG), |
Brandon Williams | e77aa33 | 2016-10-07 11:18:49 -0700 | [diff] [blame] | 751 | OPT_BOOL(0, "recurse-submodules", &recurse_submodules, |
| 752 | N_("recurse through submodules")), |
Stefan Beller | d5d09d4 | 2013-08-03 13:51:19 +0200 | [diff] [blame] | 753 | OPT_BOOL(0, "error-unmatch", &error_unmatch, |
Nguyễn Thái Ngọc Duy | 377adc3 | 2012-08-20 19:32:20 +0700 | [diff] [blame] | 754 | N_("if any <file> is not in the index, treat this as an error")), |
| 755 | OPT_STRING(0, "with-tree", &with_tree, N_("tree-ish"), |
| 756 | N_("pretend that paths removed since <tree-ish> are still present")), |
Miklos Vajna | ce8e880 | 2009-02-17 15:27:11 +0100 | [diff] [blame] | 757 | OPT__ABBREV(&abbrev), |
Stefan Beller | d5d09d4 | 2013-08-03 13:51:19 +0200 | [diff] [blame] | 758 | OPT_BOOL(0, "debug", &debug_mode, N_("show debugging data")), |
ZheNing Hu | 93a7d98 | 2021-01-23 10:20:10 +0000 | [diff] [blame] | 759 | OPT_BOOL(0, "deduplicate", &skipping_duplicates, |
| 760 | N_("suppress duplicate entries")), |
Derrick Stolee | 7808709 | 2021-12-22 14:20:53 +0000 | [diff] [blame] | 761 | OPT_BOOL(0, "sparse", &show_sparse_dirs, |
| 762 | N_("show sparse directories in the presence of a sparse index")), |
ZheNing Hu | ce74de9 | 2022-07-23 06:44:45 +0000 | [diff] [blame] | 763 | OPT_STRING_F(0, "format", &format, N_("format"), |
| 764 | N_("format to use for the output"), |
| 765 | PARSE_OPT_NONEG), |
Miklos Vajna | ce8e880 | 2009-02-17 15:27:11 +0100 | [diff] [blame] | 766 | OPT_END() |
| 767 | }; |
Ævar Arnfjörð Bjarmason | eab4ac6 | 2021-10-07 12:01:35 +0200 | [diff] [blame] | 768 | int ret = 0; |
Linus Torvalds | 8695c8b | 2005-04-11 18:55:38 -0700 | [diff] [blame] | 769 | |
Nguyễn Thái Ngọc Duy | cbb3167 | 2010-10-22 01:48:14 -0500 | [diff] [blame] | 770 | if (argc == 2 && !strcmp(argv[1], "-h")) |
| 771 | usage_with_options(ls_files_usage, builtin_ls_files_options); |
| 772 | |
Derrick Stolee | 7808709 | 2021-12-22 14:20:53 +0000 | [diff] [blame] | 773 | prepare_repo_settings(the_repository); |
| 774 | the_repository->settings.command_requires_full_index = 0; |
| 775 | |
Clemens Buchacher | efad1a5 | 2010-06-03 15:39:18 +0200 | [diff] [blame] | 776 | prefix = cmd_prefix; |
Linus Torvalds | 5be4efb | 2005-08-21 12:55:33 -0700 | [diff] [blame] | 777 | if (prefix) |
Clemens Buchacher | efad1a5 | 2010-06-03 15:39:18 +0200 | [diff] [blame] | 778 | prefix_len = strlen(prefix); |
Johannes Schindelin | ef90d6d | 2008-05-14 18:46:53 +0100 | [diff] [blame] | 779 | git_config(git_default_config, NULL); |
Linus Torvalds | 5be4efb | 2005-08-21 12:55:33 -0700 | [diff] [blame] | 780 | |
Brandon Williams | 188dce1 | 2017-06-22 11:43:48 -0700 | [diff] [blame] | 781 | if (repo_read_index(the_repository) < 0) |
Nguyễn Thái Ngọc Duy | c28b3d6 | 2009-08-20 20:47:01 +0700 | [diff] [blame] | 782 | die("index file corrupt"); |
| 783 | |
Stephen Boyd | 3778292 | 2009-05-23 11:53:12 -0700 | [diff] [blame] | 784 | argc = parse_options(argc, argv, prefix, builtin_ls_files_options, |
Miklos Vajna | ce8e880 | 2009-02-17 15:27:11 +0100 | [diff] [blame] | 785 | ls_files_usage, 0); |
Derrick Stolee | 65edd96 | 2019-09-03 11:04:57 -0700 | [diff] [blame] | 786 | pl = add_pattern_list(&dir, EXC_CMDL, "--exclude option"); |
Adam Spiers | 72aeb18 | 2013-01-16 13:25:58 +0000 | [diff] [blame] | 787 | for (i = 0; i < exclude_list.nr; i++) { |
Derrick Stolee | 65edd96 | 2019-09-03 11:04:57 -0700 | [diff] [blame] | 788 | add_pattern(exclude_list.items[i].string, "", 0, pl, --exclude_args); |
Adam Spiers | 72aeb18 | 2013-01-16 13:25:58 +0000 | [diff] [blame] | 789 | } |
ZheNing Hu | ce74de9 | 2022-07-23 06:44:45 +0000 | [diff] [blame] | 790 | |
| 791 | if (format && (show_stage || show_others || show_killed || |
| 792 | show_resolve_undo || skipping_duplicates || show_eol || show_tag)) |
| 793 | usage_msg_opt(_("--format cannot be used with -s, -o, -k, -t, " |
| 794 | "--resolve-undo, --deduplicate, --eol"), |
| 795 | ls_files_usage, builtin_ls_files_options); |
| 796 | |
Ben Peart | d8c71db | 2017-09-22 12:35:42 -0400 | [diff] [blame] | 797 | if (show_tag || show_valid_bit || show_fsmonitor_bit) { |
Miklos Vajna | ce8e880 | 2009-02-17 15:27:11 +0100 | [diff] [blame] | 798 | tag_cached = "H "; |
| 799 | tag_unmerged = "M "; |
| 800 | tag_removed = "R "; |
| 801 | tag_modified = "C "; |
| 802 | tag_other = "? "; |
| 803 | tag_killed = "K "; |
Nguyễn Thái Ngọc Duy | 44a3691 | 2009-08-20 20:46:57 +0700 | [diff] [blame] | 804 | tag_skip_worktree = "S "; |
Junio C Hamano | 9d9a2f4 | 2009-12-25 10:08:04 -0800 | [diff] [blame] | 805 | tag_resolve_undo = "U "; |
Nicolas Pitre | 9ff768e | 2005-04-28 11:44:04 -0700 | [diff] [blame] | 806 | } |
Junio C Hamano | de2e3b0 | 2009-03-20 14:30:51 -0700 | [diff] [blame] | 807 | if (show_modified || show_others || show_deleted || (dir.flags & DIR_SHOW_IGNORED) || show_killed) |
Miklos Vajna | ce8e880 | 2009-02-17 15:27:11 +0100 | [diff] [blame] | 808 | require_work_tree = 1; |
| 809 | if (show_unmerged) |
| 810 | /* |
| 811 | * There's no point in showing unmerged unless |
| 812 | * you also show the stage information. |
| 813 | */ |
| 814 | show_stage = 1; |
ZheNing Hu | 93a7d98 | 2021-01-23 10:20:10 +0000 | [diff] [blame] | 815 | if (show_tag || show_stage) |
| 816 | skipping_duplicates = 0; |
Miklos Vajna | ce8e880 | 2009-02-17 15:27:11 +0100 | [diff] [blame] | 817 | if (dir.exclude_per_dir) |
| 818 | exc_given = 1; |
Nicolas Pitre | 9ff768e | 2005-04-28 11:44:04 -0700 | [diff] [blame] | 819 | |
Mike Hommey | 7d8ae93 | 2007-11-03 12:23:12 +0100 | [diff] [blame] | 820 | if (require_work_tree && !is_inside_work_tree()) |
| 821 | setup_work_tree(); |
Johannes Schindelin | 6d9ba67 | 2007-01-23 13:30:20 +0100 | [diff] [blame] | 822 | |
Brandon Williams | e77aa33 | 2016-10-07 11:18:49 -0700 | [diff] [blame] | 823 | if (recurse_submodules && |
Jonathan Tan | 290eada | 2022-02-23 16:23:03 -0800 | [diff] [blame] | 824 | (show_deleted || show_others || show_unmerged || |
Brandon Williams | 07c01b9 | 2016-10-07 11:18:50 -0700 | [diff] [blame] | 825 | show_killed || show_modified || show_resolve_undo || with_tree)) |
Brandon Williams | e77aa33 | 2016-10-07 11:18:49 -0700 | [diff] [blame] | 826 | die("ls-files --recurse-submodules unsupported mode"); |
| 827 | |
| 828 | if (recurse_submodules && error_unmatch) |
| 829 | die("ls-files --recurse-submodules does not support " |
| 830 | "--error-unmatch"); |
| 831 | |
Nguyễn Thái Ngọc Duy | 9e06d6e | 2013-07-14 15:35:43 +0700 | [diff] [blame] | 832 | parse_pathspec(&pathspec, 0, |
Brandon Williams | cbca060 | 2017-05-11 15:04:25 -0700 | [diff] [blame] | 833 | PATHSPEC_PREFER_CWD, |
Nguyễn Thái Ngọc Duy | 9e06d6e | 2013-07-14 15:35:43 +0700 | [diff] [blame] | 834 | prefix, argv); |
Johannes Schindelin | f3670a5 | 2009-02-07 14:43:03 +0100 | [diff] [blame] | 835 | |
Brandon Williams | 75a6315 | 2016-10-07 11:18:51 -0700 | [diff] [blame] | 836 | /* |
| 837 | * Find common prefix for all pathspec's |
| 838 | * This is used as a performance optimization which unfortunately cannot |
Brandon Williams | 188dce1 | 2017-06-22 11:43:48 -0700 | [diff] [blame] | 839 | * be done when recursing into submodules because when a pathspec is |
| 840 | * given which spans repository boundaries you can't simply remove the |
| 841 | * submodule entry because the pathspec may match something inside the |
| 842 | * submodule. |
Brandon Williams | 75a6315 | 2016-10-07 11:18:51 -0700 | [diff] [blame] | 843 | */ |
| 844 | if (recurse_submodules) |
| 845 | max_prefix = NULL; |
| 846 | else |
| 847 | max_prefix = common_prefix(&pathspec); |
Brandon Williams | cbca060 | 2017-05-11 15:04:25 -0700 | [diff] [blame] | 848 | max_prefix_len = get_common_prefix_len(max_prefix); |
| 849 | |
Brandon Williams | 188dce1 | 2017-06-22 11:43:48 -0700 | [diff] [blame] | 850 | prune_index(the_repository->index, max_prefix, max_prefix_len); |
Linus Torvalds | 5be4efb | 2005-08-21 12:55:33 -0700 | [diff] [blame] | 851 | |
Junio C Hamano | bba319b | 2006-02-14 12:40:20 -0800 | [diff] [blame] | 852 | /* Treat unmatching pathspec elements as errors */ |
Nguyễn Thái Ngọc Duy | 9e06d6e | 2013-07-14 15:35:43 +0700 | [diff] [blame] | 853 | if (pathspec.nr && error_unmatch) |
Junio C Hamano | 8b54c23 | 2015-08-20 09:57:32 -0700 | [diff] [blame] | 854 | ps_matched = xcalloc(pathspec.nr, 1); |
Junio C Hamano | bba319b | 2006-02-14 12:40:20 -0800 | [diff] [blame] | 855 | |
Elijah Newren | b338e9f | 2021-05-12 17:28:16 +0000 | [diff] [blame] | 856 | if ((dir.flags & DIR_SHOW_IGNORED) && !show_others && !show_cached) |
| 857 | die("ls-files -i must be used with either -o or -c"); |
| 858 | |
Ben Walton | ac78b00 | 2009-10-08 21:53:35 -0400 | [diff] [blame] | 859 | if ((dir.flags & DIR_SHOW_IGNORED) && !exc_given) |
| 860 | die("ls-files --ignored needs some exclude pattern"); |
Linus Torvalds | 8695c8b | 2005-04-11 18:55:38 -0700 | [diff] [blame] | 861 | |
| 862 | /* With no flags, we default to showing the cached files */ |
René Scharfe | 0b437a1 | 2013-06-13 20:19:44 +0200 | [diff] [blame] | 863 | if (!(show_stage || show_deleted || show_others || show_unmerged || |
| 864 | show_killed || show_modified || show_resolve_undo)) |
Linus Torvalds | 8695c8b | 2005-04-11 18:55:38 -0700 | [diff] [blame] | 865 | show_cached = 1; |
| 866 | |
Junio C Hamano | 64586e7 | 2007-09-12 16:04:22 -0700 | [diff] [blame] | 867 | if (with_tree) { |
| 868 | /* |
| 869 | * Basic sanity check; show-stages and show-unmerged |
| 870 | * would not make any sense with this option. |
| 871 | */ |
| 872 | if (show_stage || show_unmerged) |
Jean-Noël Avila | 12909b6 | 2022-01-05 20:02:16 +0000 | [diff] [blame] | 873 | die(_("options '%s' and '%s' cannot be used together"), "ls-files --with-tree", "-s/-u"); |
Brandon Williams | 188dce1 | 2017-06-22 11:43:48 -0700 | [diff] [blame] | 874 | overlay_tree_on_index(the_repository->index, with_tree, max_prefix); |
Junio C Hamano | 64586e7 | 2007-09-12 16:04:22 -0700 | [diff] [blame] | 875 | } |
Brandon Williams | 188dce1 | 2017-06-22 11:43:48 -0700 | [diff] [blame] | 876 | |
| 877 | show_files(the_repository, &dir); |
| 878 | |
Junio C Hamano | 9d9a2f4 | 2009-12-25 10:08:04 -0800 | [diff] [blame] | 879 | if (show_resolve_undo) |
Brandon Williams | 188dce1 | 2017-06-22 11:43:48 -0700 | [diff] [blame] | 880 | show_ru_info(the_repository->index); |
Junio C Hamano | bba319b | 2006-02-14 12:40:20 -0800 | [diff] [blame] | 881 | |
Ævar Arnfjörð Bjarmason | eab4ac6 | 2021-10-07 12:01:35 +0200 | [diff] [blame] | 882 | if (ps_matched && report_path_error(ps_matched, &pathspec)) { |
| 883 | fprintf(stderr, "Did you forget to 'git add'?\n"); |
| 884 | ret = 1; |
Junio C Hamano | bba319b | 2006-02-14 12:40:20 -0800 | [diff] [blame] | 885 | } |
| 886 | |
Ævar Arnfjörð Bjarmason | 272f0a5 | 2021-10-07 12:01:36 +0200 | [diff] [blame] | 887 | string_list_clear(&exclude_list, 0); |
Elijah Newren | eceba53 | 2020-08-18 22:58:26 +0000 | [diff] [blame] | 888 | dir_clear(&dir); |
Andrzej Hunt | 4c217a4 | 2021-04-25 14:16:10 +0000 | [diff] [blame] | 889 | free(max_prefix); |
Ævar Arnfjörð Bjarmason | eab4ac6 | 2021-10-07 12:01:35 +0200 | [diff] [blame] | 890 | return ret; |
Linus Torvalds | 8695c8b | 2005-04-11 18:55:38 -0700 | [diff] [blame] | 891 | } |