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 | */ |
| 6 | #include "cache.h" |
Brandon Williams | b2141fc | 2017-06-14 11:07:36 -0700 | [diff] [blame] | 7 | #include "config.h" |
Stefan Beller | cbd53a2 | 2018-05-15 16:42:15 -0700 | [diff] [blame] | 8 | #include "object-store.h" |
Junio C Hamano | 6af1f01 | 2005-05-28 00:05:38 -0700 | [diff] [blame] | 9 | #include "blob.h" |
| 10 | #include "tree.h" |
Linus Torvalds | f35a6d3 | 2007-04-09 21:20:29 -0700 | [diff] [blame] | 11 | #include "commit.h" |
Junio C Hamano | 22ddf71 | 2005-10-14 21:56:46 -0700 | [diff] [blame] | 12 | #include "quote.h" |
Peter Eriksen | aae01bd | 2006-05-23 14:15:30 +0200 | [diff] [blame] | 13 | #include "builtin.h" |
Stephen Boyd | 61fdbcf | 2009-11-13 20:34:08 -0800 | [diff] [blame] | 14 | #include "parse-options.h" |
Nguyễn Thái Ngọc Duy | 64acde9 | 2013-07-14 15:35:25 +0700 | [diff] [blame] | 15 | #include "pathspec.h" |
Petr Baudis | 7912c07 | 2005-04-13 02:02:34 -0700 | [diff] [blame] | 16 | |
Linus Torvalds | e99d59f | 2005-05-20 11:46:10 -0700 | [diff] [blame] | 17 | static int line_termination = '\n'; |
Junio C Hamano | 6af1f01 | 2005-05-28 00:05:38 -0700 | [diff] [blame] | 18 | #define LS_RECURSIVE 1 |
| 19 | #define LS_TREE_ONLY 2 |
Linus Torvalds | 0f8f45c | 2005-12-01 10:35:51 -0800 | [diff] [blame] | 20 | #define LS_SHOW_TREES 4 |
Junio C Hamano | c639a55 | 2005-12-01 14:54:00 -0800 | [diff] [blame] | 21 | #define LS_NAME_ONLY 8 |
Jakub Narebski | a5bbda8 | 2007-05-19 22:08:11 +0200 | [diff] [blame] | 22 | #define LS_SHOW_SIZE 16 |
David Rientjes | 96f1e58 | 2006-08-15 10:23:48 -0700 | [diff] [blame] | 23 | static int abbrev; |
| 24 | static int ls_options; |
Nguyễn Thái Ngọc Duy | f0096c0 | 2011-03-25 16:34:19 +0700 | [diff] [blame] | 25 | static struct pathspec pathspec; |
David Rientjes | 96f1e58 | 2006-08-15 10:23:48 -0700 | [diff] [blame] | 26 | static int chomp_prefix; |
Linus Torvalds | a633fca | 2006-07-28 22:44:25 -0700 | [diff] [blame] | 27 | static const char *ls_tree_prefix; |
Junio C Hamano | aa1c48d | 2005-04-15 08:37:05 -0700 | [diff] [blame] | 28 | |
Stephen Boyd | 61fdbcf | 2009-11-13 20:34:08 -0800 | [diff] [blame] | 29 | static const char * const ls_tree_usage[] = { |
Nguyễn Thái Ngọc Duy | 373f922 | 2012-08-20 19:32:21 +0700 | [diff] [blame] | 30 | N_("git ls-tree [<options>] <tree-ish> [<path>...]"), |
Stephen Boyd | 61fdbcf | 2009-11-13 20:34:08 -0800 | [diff] [blame] | 31 | NULL |
| 32 | }; |
Linus Torvalds | 0f8f45c | 2005-12-01 10:35:51 -0800 | [diff] [blame] | 33 | |
| 34 | static int show_recursive(const char *base, int baselen, const char *pathname) |
| 35 | { |
Brandon Williams | e1e24ed | 2017-01-04 10:03:59 -0800 | [diff] [blame] | 36 | int i; |
Linus Torvalds | 0f8f45c | 2005-12-01 10:35:51 -0800 | [diff] [blame] | 37 | |
| 38 | if (ls_options & LS_RECURSIVE) |
| 39 | return 1; |
| 40 | |
Brandon Williams | e1e24ed | 2017-01-04 10:03:59 -0800 | [diff] [blame] | 41 | if (!pathspec.nr) |
Linus Torvalds | 0f8f45c | 2005-12-01 10:35:51 -0800 | [diff] [blame] | 42 | return 0; |
| 43 | |
Brandon Williams | e1e24ed | 2017-01-04 10:03:59 -0800 | [diff] [blame] | 44 | for (i = 0; i < pathspec.nr; i++) { |
| 45 | const char *spec = pathspec.items[i].match; |
Linus Torvalds | 0f8f45c | 2005-12-01 10:35:51 -0800 | [diff] [blame] | 46 | int len, speclen; |
| 47 | |
Linus Torvalds | 0f8f45c | 2005-12-01 10:35:51 -0800 | [diff] [blame] | 48 | if (strncmp(base, spec, baselen)) |
| 49 | continue; |
| 50 | len = strlen(pathname); |
| 51 | spec += baselen; |
| 52 | speclen = strlen(spec); |
| 53 | if (speclen <= len) |
| 54 | continue; |
Junio C Hamano | b294ed6 | 2010-09-11 11:47:09 -0700 | [diff] [blame] | 55 | if (spec[len] && spec[len] != '/') |
| 56 | continue; |
Linus Torvalds | 0f8f45c | 2005-12-01 10:35:51 -0800 | [diff] [blame] | 57 | if (memcmp(pathname, spec, len)) |
| 58 | continue; |
| 59 | return 1; |
| 60 | } |
Brandon Williams | e1e24ed | 2017-01-04 10:03:59 -0800 | [diff] [blame] | 61 | return 0; |
Linus Torvalds | 0f8f45c | 2005-12-01 10:35:51 -0800 | [diff] [blame] | 62 | } |
Junio C Hamano | aa1c48d | 2005-04-15 08:37:05 -0700 | [diff] [blame] | 63 | |
brian m. carlson | df46d77 | 2018-03-12 02:27:26 +0000 | [diff] [blame] | 64 | static int show_tree(const struct object_id *oid, struct strbuf *base, |
Ævar Arnfjörð Bjarmason | 4795748 | 2021-03-20 23:37:51 +0100 | [diff] [blame] | 65 | const char *pathname, unsigned mode, void *context) |
Petr Baudis | 7912c07 | 2005-04-13 02:02:34 -0700 | [diff] [blame] | 66 | { |
Linus Torvalds | 0f8f45c | 2005-12-01 10:35:51 -0800 | [diff] [blame] | 67 | int retval = 0; |
Nguyễn Thái Ngọc Duy | 1cf9952 | 2014-11-30 16:05:01 +0700 | [diff] [blame] | 68 | int baselen; |
Peter Eriksen | 8e44025 | 2006-04-02 14:44:09 +0200 | [diff] [blame] | 69 | const char *type = blob_type; |
Petr Baudis | 7912c07 | 2005-04-13 02:02:34 -0700 | [diff] [blame] | 70 | |
Martin Waitz | 302b928 | 2007-05-21 22:08:28 +0200 | [diff] [blame] | 71 | if (S_ISGITLINK(mode)) { |
Linus Torvalds | f35a6d3 | 2007-04-09 21:20:29 -0700 | [diff] [blame] | 72 | /* |
| 73 | * Maybe we want to have some recursive version here? |
| 74 | * |
Anders Melchiorsen | 7d0b18a | 2008-08-04 12:18:40 +0200 | [diff] [blame] | 75 | * Something similar to this incomplete example: |
Linus Torvalds | f35a6d3 | 2007-04-09 21:20:29 -0700 | [diff] [blame] | 76 | * |
Lars Hjemli | d3bee16 | 2009-01-25 01:52:05 +0100 | [diff] [blame] | 77 | if (show_subprojects(base, baselen, pathname)) |
| 78 | retval = READ_TREE_RECURSIVE; |
Linus Torvalds | f35a6d3 | 2007-04-09 21:20:29 -0700 | [diff] [blame] | 79 | * |
Linus Torvalds | f35a6d3 | 2007-04-09 21:20:29 -0700 | [diff] [blame] | 80 | */ |
| 81 | type = commit_type; |
| 82 | } else if (S_ISDIR(mode)) { |
Nguyễn Thái Ngọc Duy | 6a0b0b6 | 2014-11-30 16:05:00 +0700 | [diff] [blame] | 83 | if (show_recursive(base->buf, base->len, pathname)) { |
Linus Torvalds | 0f8f45c | 2005-12-01 10:35:51 -0800 | [diff] [blame] | 84 | retval = READ_TREE_RECURSIVE; |
| 85 | if (!(ls_options & LS_SHOW_TREES)) |
| 86 | return retval; |
Linus Torvalds | e246637 | 2005-11-27 22:48:08 -0800 | [diff] [blame] | 87 | } |
Peter Eriksen | 8e44025 | 2006-04-02 14:44:09 +0200 | [diff] [blame] | 88 | type = tree_type; |
Linus Torvalds | 3c5e846 | 2005-11-26 09:38:20 -0800 | [diff] [blame] | 89 | } |
Junio C Hamano | f598467 | 2005-12-01 13:15:20 -0800 | [diff] [blame] | 90 | else if (ls_options & LS_TREE_ONLY) |
| 91 | return 0; |
Linus Torvalds | 3c5e846 | 2005-11-26 09:38:20 -0800 | [diff] [blame] | 92 | |
Jakub Narebski | a5bbda8 | 2007-05-19 22:08:11 +0200 | [diff] [blame] | 93 | if (!(ls_options & LS_NAME_ONLY)) { |
| 94 | if (ls_options & LS_SHOW_SIZE) { |
Alex Riesen | e392a85 | 2009-03-19 23:54:29 +0100 | [diff] [blame] | 95 | char size_text[24]; |
Jakub Narebski | a5bbda8 | 2007-05-19 22:08:11 +0200 | [diff] [blame] | 96 | if (!strcmp(type, blob_type)) { |
Alex Riesen | e392a85 | 2009-03-19 23:54:29 +0100 | [diff] [blame] | 97 | unsigned long size; |
Stefan Beller | 0df8e96 | 2018-04-25 11:20:59 -0700 | [diff] [blame] | 98 | if (oid_object_info(the_repository, oid, &size) == OBJ_BAD) |
Jeff King | 5096d49 | 2015-09-24 17:06:08 -0400 | [diff] [blame] | 99 | xsnprintf(size_text, sizeof(size_text), |
| 100 | "BAD"); |
Alex Riesen | e392a85 | 2009-03-19 23:54:29 +0100 | [diff] [blame] | 101 | else |
Jeff King | 5096d49 | 2015-09-24 17:06:08 -0400 | [diff] [blame] | 102 | xsnprintf(size_text, sizeof(size_text), |
Torsten Bögershausen | ca473ce | 2018-11-11 08:05:04 +0100 | [diff] [blame] | 103 | "%"PRIuMAX, (uintmax_t)size); |
Jakub Narebski | a5bbda8 | 2007-05-19 22:08:11 +0200 | [diff] [blame] | 104 | } else |
Jeff King | 5096d49 | 2015-09-24 17:06:08 -0400 | [diff] [blame] | 105 | xsnprintf(size_text, sizeof(size_text), "-"); |
Alex Riesen | e392a85 | 2009-03-19 23:54:29 +0100 | [diff] [blame] | 106 | printf("%06o %s %s %7s\t", mode, type, |
brian m. carlson | aab9583 | 2018-03-12 02:27:30 +0000 | [diff] [blame] | 107 | find_unique_abbrev(oid, abbrev), |
Alex Riesen | e392a85 | 2009-03-19 23:54:29 +0100 | [diff] [blame] | 108 | size_text); |
Jakub Narebski | a5bbda8 | 2007-05-19 22:08:11 +0200 | [diff] [blame] | 109 | } else |
| 110 | printf("%06o %s %s\t", mode, type, |
brian m. carlson | aab9583 | 2018-03-12 02:27:30 +0000 | [diff] [blame] | 111 | find_unique_abbrev(oid, abbrev)); |
Jakub Narebski | a5bbda8 | 2007-05-19 22:08:11 +0200 | [diff] [blame] | 112 | } |
Nguyễn Thái Ngọc Duy | 1cf9952 | 2014-11-30 16:05:01 +0700 | [diff] [blame] | 113 | baselen = base->len; |
| 114 | strbuf_addstr(base, pathname); |
| 115 | write_name_quoted_relative(base->buf, |
| 116 | chomp_prefix ? ls_tree_prefix : NULL, |
| 117 | stdout, line_termination); |
| 118 | strbuf_setlen(base, baselen); |
Linus Torvalds | 0f8f45c | 2005-12-01 10:35:51 -0800 | [diff] [blame] | 119 | return retval; |
Linus Torvalds | 3c5e846 | 2005-11-26 09:38:20 -0800 | [diff] [blame] | 120 | } |
| 121 | |
Linus Torvalds | a633fca | 2006-07-28 22:44:25 -0700 | [diff] [blame] | 122 | int cmd_ls_tree(int argc, const char **argv, const char *prefix) |
Linus Torvalds | 3c5e846 | 2005-11-26 09:38:20 -0800 | [diff] [blame] | 123 | { |
brian m. carlson | a9b5f5b | 2017-05-06 22:10:34 +0000 | [diff] [blame] | 124 | struct object_id oid; |
Daniel Barkalow | 521698b | 2006-01-26 01:13:36 -0500 | [diff] [blame] | 125 | struct tree *tree; |
Nguyễn Thái Ngọc Duy | f0096c0 | 2011-03-25 16:34:19 +0700 | [diff] [blame] | 126 | int i, full_tree = 0; |
Stephen Boyd | 61fdbcf | 2009-11-13 20:34:08 -0800 | [diff] [blame] | 127 | const struct option ls_tree_options[] = { |
Nguyễn Thái Ngọc Duy | 373f922 | 2012-08-20 19:32:21 +0700 | [diff] [blame] | 128 | OPT_BIT('d', NULL, &ls_options, N_("only show trees"), |
Stephen Boyd | 61fdbcf | 2009-11-13 20:34:08 -0800 | [diff] [blame] | 129 | LS_TREE_ONLY), |
Nguyễn Thái Ngọc Duy | 373f922 | 2012-08-20 19:32:21 +0700 | [diff] [blame] | 130 | OPT_BIT('r', NULL, &ls_options, N_("recurse into subtrees"), |
Stephen Boyd | 61fdbcf | 2009-11-13 20:34:08 -0800 | [diff] [blame] | 131 | LS_RECURSIVE), |
Nguyễn Thái Ngọc Duy | 373f922 | 2012-08-20 19:32:21 +0700 | [diff] [blame] | 132 | OPT_BIT('t', NULL, &ls_options, N_("show trees when recursing"), |
Stephen Boyd | 61fdbcf | 2009-11-13 20:34:08 -0800 | [diff] [blame] | 133 | LS_SHOW_TREES), |
| 134 | OPT_SET_INT('z', NULL, &line_termination, |
Nguyễn Thái Ngọc Duy | 373f922 | 2012-08-20 19:32:21 +0700 | [diff] [blame] | 135 | N_("terminate entries with NUL byte"), 0), |
| 136 | OPT_BIT('l', "long", &ls_options, N_("include object size"), |
Stephen Boyd | 61fdbcf | 2009-11-13 20:34:08 -0800 | [diff] [blame] | 137 | LS_SHOW_SIZE), |
Nguyễn Thái Ngọc Duy | 373f922 | 2012-08-20 19:32:21 +0700 | [diff] [blame] | 138 | OPT_BIT(0, "name-only", &ls_options, N_("list only filenames"), |
Stephen Boyd | 61fdbcf | 2009-11-13 20:34:08 -0800 | [diff] [blame] | 139 | LS_NAME_ONLY), |
Nguyễn Thái Ngọc Duy | 373f922 | 2012-08-20 19:32:21 +0700 | [diff] [blame] | 140 | OPT_BIT(0, "name-status", &ls_options, N_("list only filenames"), |
Stephen Boyd | 61fdbcf | 2009-11-13 20:34:08 -0800 | [diff] [blame] | 141 | LS_NAME_ONLY), |
| 142 | OPT_SET_INT(0, "full-name", &chomp_prefix, |
Nguyễn Thái Ngọc Duy | 373f922 | 2012-08-20 19:32:21 +0700 | [diff] [blame] | 143 | N_("use full path names"), 0), |
Stefan Beller | d5d09d4 | 2013-08-03 13:51:19 +0200 | [diff] [blame] | 144 | OPT_BOOL(0, "full-tree", &full_tree, |
| 145 | N_("list entire tree; not just current directory " |
| 146 | "(implies --full-name)")), |
Stephen Boyd | 61fdbcf | 2009-11-13 20:34:08 -0800 | [diff] [blame] | 147 | OPT__ABBREV(&abbrev), |
| 148 | OPT_END() |
| 149 | }; |
Linus Torvalds | 3c5e846 | 2005-11-26 09:38:20 -0800 | [diff] [blame] | 150 | |
Johannes Schindelin | ef90d6d | 2008-05-14 18:46:53 +0100 | [diff] [blame] | 151 | git_config(git_default_config, NULL); |
Linus Torvalds | a633fca | 2006-07-28 22:44:25 -0700 | [diff] [blame] | 152 | ls_tree_prefix = prefix; |
Junio C Hamano | a69dd58 | 2005-12-23 13:39:30 -0800 | [diff] [blame] | 153 | if (prefix && *prefix) |
| 154 | chomp_prefix = strlen(prefix); |
Stephen Boyd | 61fdbcf | 2009-11-13 20:34:08 -0800 | [diff] [blame] | 155 | |
| 156 | argc = parse_options(argc, argv, prefix, ls_tree_options, |
| 157 | ls_tree_usage, 0); |
| 158 | if (full_tree) { |
| 159 | ls_tree_prefix = prefix = NULL; |
| 160 | chomp_prefix = 0; |
Junio C Hamano | aa1c48d | 2005-04-15 08:37:05 -0700 | [diff] [blame] | 161 | } |
Junio C Hamano | f598467 | 2005-12-01 13:15:20 -0800 | [diff] [blame] | 162 | /* -d -r should imply -t, but -d by itself should not have to. */ |
| 163 | if ( (LS_TREE_ONLY|LS_RECURSIVE) == |
| 164 | ((LS_TREE_ONLY|LS_RECURSIVE) & ls_options)) |
| 165 | ls_options |= LS_SHOW_TREES; |
Junio C Hamano | aa1c48d | 2005-04-15 08:37:05 -0700 | [diff] [blame] | 166 | |
Stephen Boyd | 61fdbcf | 2009-11-13 20:34:08 -0800 | [diff] [blame] | 167 | if (argc < 1) |
| 168 | usage_with_options(ls_tree_usage, ls_tree_options); |
brian m. carlson | a9b5f5b | 2017-05-06 22:10:34 +0000 | [diff] [blame] | 169 | if (get_oid(argv[0], &oid)) |
Stephen Boyd | 61fdbcf | 2009-11-13 20:34:08 -0800 | [diff] [blame] | 170 | die("Not a valid object name %s", argv[0]); |
Junio C Hamano | 6af1f01 | 2005-05-28 00:05:38 -0700 | [diff] [blame] | 171 | |
Nguyễn Thái Ngọc Duy | 0fdc2ae | 2013-07-14 15:35:31 +0700 | [diff] [blame] | 172 | /* |
| 173 | * show_recursive() rolls its own matching code and is |
| 174 | * generally ignorant of 'struct pathspec'. The magic mask |
| 175 | * 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] | 176 | * match_pathspec() or tree_entry_interesting() |
Nguyễn Thái Ngọc Duy | 0fdc2ae | 2013-07-14 15:35:31 +0700 | [diff] [blame] | 177 | */ |
Brandon Williams | e1e24ed | 2017-01-04 10:03:59 -0800 | [diff] [blame] | 178 | parse_pathspec(&pathspec, PATHSPEC_ALL_MAGIC & |
| 179 | ~(PATHSPEC_FROMTOP | PATHSPEC_LITERAL), |
Nguyễn Thái Ngọc Duy | 0fdc2ae | 2013-07-14 15:35:31 +0700 | [diff] [blame] | 180 | PATHSPEC_PREFER_CWD, |
| 181 | prefix, argv + 1); |
Nguyễn Thái Ngọc Duy | f0096c0 | 2011-03-25 16:34:19 +0700 | [diff] [blame] | 182 | for (i = 0; i < pathspec.nr; i++) |
Nguyễn Thái Ngọc Duy | 170260a | 2012-11-18 16:13:06 +0700 | [diff] [blame] | 183 | pathspec.items[i].nowildcard_len = pathspec.items[i].len; |
Junio C Hamano | 33e0f62 | 2011-04-05 09:30:36 -0700 | [diff] [blame] | 184 | pathspec.has_wildcard = 0; |
brian m. carlson | a9dbc17 | 2017-05-06 22:10:37 +0000 | [diff] [blame] | 185 | tree = parse_tree_indirect(&oid); |
Daniel Barkalow | 521698b | 2006-01-26 01:13:36 -0500 | [diff] [blame] | 186 | if (!tree) |
Linus Torvalds | 3c5e846 | 2005-11-26 09:38:20 -0800 | [diff] [blame] | 187 | die("not a tree object"); |
Ævar Arnfjörð Bjarmason | 4795748 | 2021-03-20 23:37:51 +0100 | [diff] [blame] | 188 | return !!read_tree(the_repository, tree, |
| 189 | &pathspec, show_tree, NULL); |
Petr Baudis | 7912c07 | 2005-04-13 02:02:34 -0700 | [diff] [blame] | 190 | } |