blob: 3a442631c71a07f0d0dda791ed72af83f2b92bca [file] [log] [blame]
Petr Baudis7912c072005-04-13 02:02:34 -07001/*
2 * GIT - The information manager from hell
3 *
4 * Copyright (C) Linus Torvalds, 2005
5 */
6#include "cache.h"
Brandon Williamsb2141fc2017-06-14 11:07:36 -07007#include "config.h"
Stefan Bellercbd53a22018-05-15 16:42:15 -07008#include "object-store.h"
Junio C Hamano6af1f012005-05-28 00:05:38 -07009#include "blob.h"
10#include "tree.h"
Linus Torvaldsf35a6d32007-04-09 21:20:29 -070011#include "commit.h"
Junio C Hamano22ddf712005-10-14 21:56:46 -070012#include "quote.h"
Peter Eriksenaae01bd2006-05-23 14:15:30 +020013#include "builtin.h"
Stephen Boyd61fdbcf2009-11-13 20:34:08 -080014#include "parse-options.h"
Nguyễn Thái Ngọc Duy64acde92013-07-14 15:35:25 +070015#include "pathspec.h"
Petr Baudis7912c072005-04-13 02:02:34 -070016
Linus Torvaldse99d59f2005-05-20 11:46:10 -070017static int line_termination = '\n';
Junio C Hamano6af1f012005-05-28 00:05:38 -070018#define LS_RECURSIVE 1
19#define LS_TREE_ONLY 2
Linus Torvalds0f8f45c2005-12-01 10:35:51 -080020#define LS_SHOW_TREES 4
Junio C Hamanoc639a552005-12-01 14:54:00 -080021#define LS_NAME_ONLY 8
Jakub Narebskia5bbda82007-05-19 22:08:11 +020022#define LS_SHOW_SIZE 16
David Rientjes96f1e582006-08-15 10:23:48 -070023static int abbrev;
24static int ls_options;
Nguyễn Thái Ngọc Duyf0096c02011-03-25 16:34:19 +070025static struct pathspec pathspec;
David Rientjes96f1e582006-08-15 10:23:48 -070026static int chomp_prefix;
Linus Torvaldsa633fca2006-07-28 22:44:25 -070027static const char *ls_tree_prefix;
Junio C Hamanoaa1c48d2005-04-15 08:37:05 -070028
Stephen Boyd61fdbcf2009-11-13 20:34:08 -080029static const char * const ls_tree_usage[] = {
Nguyễn Thái Ngọc Duy373f9222012-08-20 19:32:21 +070030 N_("git ls-tree [<options>] <tree-ish> [<path>...]"),
Stephen Boyd61fdbcf2009-11-13 20:34:08 -080031 NULL
32};
Linus Torvalds0f8f45c2005-12-01 10:35:51 -080033
34static int show_recursive(const char *base, int baselen, const char *pathname)
35{
Brandon Williamse1e24ed2017-01-04 10:03:59 -080036 int i;
Linus Torvalds0f8f45c2005-12-01 10:35:51 -080037
38 if (ls_options & LS_RECURSIVE)
39 return 1;
40
Brandon Williamse1e24ed2017-01-04 10:03:59 -080041 if (!pathspec.nr)
Linus Torvalds0f8f45c2005-12-01 10:35:51 -080042 return 0;
43
Brandon Williamse1e24ed2017-01-04 10:03:59 -080044 for (i = 0; i < pathspec.nr; i++) {
45 const char *spec = pathspec.items[i].match;
Linus Torvalds0f8f45c2005-12-01 10:35:51 -080046 int len, speclen;
47
Linus Torvalds0f8f45c2005-12-01 10:35:51 -080048 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 Hamanob294ed62010-09-11 11:47:09 -070055 if (spec[len] && spec[len] != '/')
56 continue;
Linus Torvalds0f8f45c2005-12-01 10:35:51 -080057 if (memcmp(pathname, spec, len))
58 continue;
59 return 1;
60 }
Brandon Williamse1e24ed2017-01-04 10:03:59 -080061 return 0;
Linus Torvalds0f8f45c2005-12-01 10:35:51 -080062}
Junio C Hamanoaa1c48d2005-04-15 08:37:05 -070063
brian m. carlsondf46d772018-03-12 02:27:26 +000064static int show_tree(const struct object_id *oid, struct strbuf *base,
Ævar Arnfjörð Bjarmason47957482021-03-20 23:37:51 +010065 const char *pathname, unsigned mode, void *context)
Petr Baudis7912c072005-04-13 02:02:34 -070066{
Linus Torvalds0f8f45c2005-12-01 10:35:51 -080067 int retval = 0;
Nguyễn Thái Ngọc Duy1cf99522014-11-30 16:05:01 +070068 int baselen;
Peter Eriksen8e440252006-04-02 14:44:09 +020069 const char *type = blob_type;
Petr Baudis7912c072005-04-13 02:02:34 -070070
Martin Waitz302b9282007-05-21 22:08:28 +020071 if (S_ISGITLINK(mode)) {
Linus Torvaldsf35a6d32007-04-09 21:20:29 -070072 /*
73 * Maybe we want to have some recursive version here?
74 *
Anders Melchiorsen7d0b18a2008-08-04 12:18:40 +020075 * Something similar to this incomplete example:
Linus Torvaldsf35a6d32007-04-09 21:20:29 -070076 *
Lars Hjemlid3bee162009-01-25 01:52:05 +010077 if (show_subprojects(base, baselen, pathname))
78 retval = READ_TREE_RECURSIVE;
Linus Torvaldsf35a6d32007-04-09 21:20:29 -070079 *
Linus Torvaldsf35a6d32007-04-09 21:20:29 -070080 */
81 type = commit_type;
82 } else if (S_ISDIR(mode)) {
Nguyễn Thái Ngọc Duy6a0b0b62014-11-30 16:05:00 +070083 if (show_recursive(base->buf, base->len, pathname)) {
Linus Torvalds0f8f45c2005-12-01 10:35:51 -080084 retval = READ_TREE_RECURSIVE;
85 if (!(ls_options & LS_SHOW_TREES))
86 return retval;
Linus Torvaldse2466372005-11-27 22:48:08 -080087 }
Peter Eriksen8e440252006-04-02 14:44:09 +020088 type = tree_type;
Linus Torvalds3c5e8462005-11-26 09:38:20 -080089 }
Junio C Hamanof5984672005-12-01 13:15:20 -080090 else if (ls_options & LS_TREE_ONLY)
91 return 0;
Linus Torvalds3c5e8462005-11-26 09:38:20 -080092
Jakub Narebskia5bbda82007-05-19 22:08:11 +020093 if (!(ls_options & LS_NAME_ONLY)) {
94 if (ls_options & LS_SHOW_SIZE) {
Alex Riesene392a852009-03-19 23:54:29 +010095 char size_text[24];
Jakub Narebskia5bbda82007-05-19 22:08:11 +020096 if (!strcmp(type, blob_type)) {
Alex Riesene392a852009-03-19 23:54:29 +010097 unsigned long size;
Stefan Beller0df8e962018-04-25 11:20:59 -070098 if (oid_object_info(the_repository, oid, &size) == OBJ_BAD)
Jeff King5096d492015-09-24 17:06:08 -040099 xsnprintf(size_text, sizeof(size_text),
100 "BAD");
Alex Riesene392a852009-03-19 23:54:29 +0100101 else
Jeff King5096d492015-09-24 17:06:08 -0400102 xsnprintf(size_text, sizeof(size_text),
Torsten Bögershausenca473ce2018-11-11 08:05:04 +0100103 "%"PRIuMAX, (uintmax_t)size);
Jakub Narebskia5bbda82007-05-19 22:08:11 +0200104 } else
Jeff King5096d492015-09-24 17:06:08 -0400105 xsnprintf(size_text, sizeof(size_text), "-");
Alex Riesene392a852009-03-19 23:54:29 +0100106 printf("%06o %s %s %7s\t", mode, type,
brian m. carlsonaab95832018-03-12 02:27:30 +0000107 find_unique_abbrev(oid, abbrev),
Alex Riesene392a852009-03-19 23:54:29 +0100108 size_text);
Jakub Narebskia5bbda82007-05-19 22:08:11 +0200109 } else
110 printf("%06o %s %s\t", mode, type,
brian m. carlsonaab95832018-03-12 02:27:30 +0000111 find_unique_abbrev(oid, abbrev));
Jakub Narebskia5bbda82007-05-19 22:08:11 +0200112 }
Nguyễn Thái Ngọc Duy1cf99522014-11-30 16:05:01 +0700113 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 Torvalds0f8f45c2005-12-01 10:35:51 -0800119 return retval;
Linus Torvalds3c5e8462005-11-26 09:38:20 -0800120}
121
Linus Torvaldsa633fca2006-07-28 22:44:25 -0700122int cmd_ls_tree(int argc, const char **argv, const char *prefix)
Linus Torvalds3c5e8462005-11-26 09:38:20 -0800123{
brian m. carlsona9b5f5b2017-05-06 22:10:34 +0000124 struct object_id oid;
Daniel Barkalow521698b2006-01-26 01:13:36 -0500125 struct tree *tree;
Nguyễn Thái Ngọc Duyf0096c02011-03-25 16:34:19 +0700126 int i, full_tree = 0;
Stephen Boyd61fdbcf2009-11-13 20:34:08 -0800127 const struct option ls_tree_options[] = {
Nguyễn Thái Ngọc Duy373f9222012-08-20 19:32:21 +0700128 OPT_BIT('d', NULL, &ls_options, N_("only show trees"),
Stephen Boyd61fdbcf2009-11-13 20:34:08 -0800129 LS_TREE_ONLY),
Nguyễn Thái Ngọc Duy373f9222012-08-20 19:32:21 +0700130 OPT_BIT('r', NULL, &ls_options, N_("recurse into subtrees"),
Stephen Boyd61fdbcf2009-11-13 20:34:08 -0800131 LS_RECURSIVE),
Nguyễn Thái Ngọc Duy373f9222012-08-20 19:32:21 +0700132 OPT_BIT('t', NULL, &ls_options, N_("show trees when recursing"),
Stephen Boyd61fdbcf2009-11-13 20:34:08 -0800133 LS_SHOW_TREES),
134 OPT_SET_INT('z', NULL, &line_termination,
Nguyễn Thái Ngọc Duy373f9222012-08-20 19:32:21 +0700135 N_("terminate entries with NUL byte"), 0),
136 OPT_BIT('l', "long", &ls_options, N_("include object size"),
Stephen Boyd61fdbcf2009-11-13 20:34:08 -0800137 LS_SHOW_SIZE),
Nguyễn Thái Ngọc Duy373f9222012-08-20 19:32:21 +0700138 OPT_BIT(0, "name-only", &ls_options, N_("list only filenames"),
Stephen Boyd61fdbcf2009-11-13 20:34:08 -0800139 LS_NAME_ONLY),
Nguyễn Thái Ngọc Duy373f9222012-08-20 19:32:21 +0700140 OPT_BIT(0, "name-status", &ls_options, N_("list only filenames"),
Stephen Boyd61fdbcf2009-11-13 20:34:08 -0800141 LS_NAME_ONLY),
142 OPT_SET_INT(0, "full-name", &chomp_prefix,
Nguyễn Thái Ngọc Duy373f9222012-08-20 19:32:21 +0700143 N_("use full path names"), 0),
Stefan Bellerd5d09d42013-08-03 13:51:19 +0200144 OPT_BOOL(0, "full-tree", &full_tree,
145 N_("list entire tree; not just current directory "
146 "(implies --full-name)")),
Stephen Boyd61fdbcf2009-11-13 20:34:08 -0800147 OPT__ABBREV(&abbrev),
148 OPT_END()
149 };
Linus Torvalds3c5e8462005-11-26 09:38:20 -0800150
Johannes Schindelinef90d6d2008-05-14 18:46:53 +0100151 git_config(git_default_config, NULL);
Linus Torvaldsa633fca2006-07-28 22:44:25 -0700152 ls_tree_prefix = prefix;
Junio C Hamanoa69dd582005-12-23 13:39:30 -0800153 if (prefix && *prefix)
154 chomp_prefix = strlen(prefix);
Stephen Boyd61fdbcf2009-11-13 20:34:08 -0800155
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 Hamanoaa1c48d2005-04-15 08:37:05 -0700161 }
Junio C Hamanof5984672005-12-01 13:15:20 -0800162 /* -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 Hamanoaa1c48d2005-04-15 08:37:05 -0700166
Stephen Boyd61fdbcf2009-11-13 20:34:08 -0800167 if (argc < 1)
168 usage_with_options(ls_tree_usage, ls_tree_options);
brian m. carlsona9b5f5b2017-05-06 22:10:34 +0000169 if (get_oid(argv[0], &oid))
Stephen Boyd61fdbcf2009-11-13 20:34:08 -0800170 die("Not a valid object name %s", argv[0]);
Junio C Hamano6af1f012005-05-28 00:05:38 -0700171
Nguyễn Thái Ngọc Duy0fdc2ae2013-07-14 15:35:31 +0700172 /*
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 Duy854b0952014-01-24 20:40:30 +0700176 * match_pathspec() or tree_entry_interesting()
Nguyễn Thái Ngọc Duy0fdc2ae2013-07-14 15:35:31 +0700177 */
Brandon Williamse1e24ed2017-01-04 10:03:59 -0800178 parse_pathspec(&pathspec, PATHSPEC_ALL_MAGIC &
179 ~(PATHSPEC_FROMTOP | PATHSPEC_LITERAL),
Nguyễn Thái Ngọc Duy0fdc2ae2013-07-14 15:35:31 +0700180 PATHSPEC_PREFER_CWD,
181 prefix, argv + 1);
Nguyễn Thái Ngọc Duyf0096c02011-03-25 16:34:19 +0700182 for (i = 0; i < pathspec.nr; i++)
Nguyễn Thái Ngọc Duy170260a2012-11-18 16:13:06 +0700183 pathspec.items[i].nowildcard_len = pathspec.items[i].len;
Junio C Hamano33e0f622011-04-05 09:30:36 -0700184 pathspec.has_wildcard = 0;
brian m. carlsona9dbc172017-05-06 22:10:37 +0000185 tree = parse_tree_indirect(&oid);
Daniel Barkalow521698b2006-01-26 01:13:36 -0500186 if (!tree)
Linus Torvalds3c5e8462005-11-26 09:38:20 -0800187 die("not a tree object");
Ævar Arnfjörð Bjarmason47957482021-03-20 23:37:51 +0100188 return !!read_tree(the_repository, tree,
189 &pathspec, show_tree, NULL);
Petr Baudis7912c072005-04-13 02:02:34 -0700190}