2 * GIT - The information manager from hell
4 * Copyright (C) Linus Torvalds, 2005
12 #include "parse-options.h"
14 static int line_termination
= '\n';
15 #define LS_RECURSIVE 1
16 #define LS_TREE_ONLY 2
17 #define LS_SHOW_TREES 4
18 #define LS_NAME_ONLY 8
19 #define LS_SHOW_SIZE 16
21 static int ls_options
;
22 static const char **pathspec
;
23 static int chomp_prefix
;
24 static const char *ls_tree_prefix
;
26 static const char * const ls_tree_usage
[] = {
27 "git ls-tree [<options>] <tree-ish> [path...]",
31 static int show_recursive(const char *base
, int baselen
, const char *pathname
)
35 if (ls_options
& LS_RECURSIVE
)
43 const char *spec
= *s
++;
48 if (strncmp(base
, spec
, baselen
))
50 len
= strlen(pathname
);
52 speclen
= strlen(spec
);
55 if (memcmp(pathname
, spec
, len
))
61 static int show_tree(const unsigned char *sha1
, const char *base
, int baselen
,
62 const char *pathname
, unsigned mode
, int stage
, void *context
)
65 const char *type
= blob_type
;
67 if (S_ISGITLINK(mode
)) {
69 * Maybe we want to have some recursive version here?
71 * Something similar to this incomplete example:
73 if (show_subprojects(base, baselen, pathname))
74 retval = READ_TREE_RECURSIVE;
78 } else if (S_ISDIR(mode
)) {
79 if (show_recursive(base
, baselen
, pathname
)) {
80 retval
= READ_TREE_RECURSIVE
;
81 if (!(ls_options
& LS_SHOW_TREES
))
86 else if (ls_options
& LS_TREE_ONLY
)
90 (baselen
< chomp_prefix
|| memcmp(ls_tree_prefix
, base
, chomp_prefix
)))
93 if (!(ls_options
& LS_NAME_ONLY
)) {
94 if (ls_options
& LS_SHOW_SIZE
) {
96 if (!strcmp(type
, blob_type
)) {
98 if (sha1_object_info(sha1
, &size
) == OBJ_BAD
)
99 strcpy(size_text
, "BAD");
101 snprintf(size_text
, sizeof(size_text
),
104 strcpy(size_text
, "-");
105 printf("%06o %s %s %7s\t", mode
, type
,
106 find_unique_abbrev(sha1
, abbrev
),
109 printf("%06o %s %s\t", mode
, type
,
110 find_unique_abbrev(sha1
, abbrev
));
112 write_name_quotedpfx(base
+ chomp_prefix
, baselen
- chomp_prefix
,
113 pathname
, stdout
, line_termination
);
117 int cmd_ls_tree(int argc
, const char **argv
, const char *prefix
)
119 unsigned char sha1
[20];
122 const struct option ls_tree_options
[] = {
123 OPT_BIT('d', NULL
, &ls_options
, "only show trees",
125 OPT_BIT('r', NULL
, &ls_options
, "recurse into subtrees",
127 OPT_BIT('t', NULL
, &ls_options
, "show trees when recursing",
129 OPT_SET_INT('z', NULL
, &line_termination
,
130 "terminate entries with NUL byte", 0),
131 OPT_BIT('l', "long", &ls_options
, "include object size",
133 OPT_BIT(0, "name-only", &ls_options
, "list only filenames",
135 OPT_BIT(0, "name-status", &ls_options
, "list only filenames",
137 OPT_SET_INT(0, "full-name", &chomp_prefix
,
138 "use full path names", 0),
139 OPT_BOOLEAN(0, "full-tree", &full_tree
,
140 "list entire tree; not just current directory "
141 "(implies --full-name)"),
142 OPT__ABBREV(&abbrev
),
146 git_config(git_default_config
, NULL
);
147 ls_tree_prefix
= prefix
;
148 if (prefix
&& *prefix
)
149 chomp_prefix
= strlen(prefix
);
151 argc
= parse_options(argc
, argv
, prefix
, ls_tree_options
,
154 ls_tree_prefix
= prefix
= NULL
;
157 /* -d -r should imply -t, but -d by itself should not have to. */
158 if ( (LS_TREE_ONLY
|LS_RECURSIVE
) ==
159 ((LS_TREE_ONLY
|LS_RECURSIVE
) & ls_options
))
160 ls_options
|= LS_SHOW_TREES
;
163 usage_with_options(ls_tree_usage
, ls_tree_options
);
164 if (get_sha1(argv
[0], sha1
))
165 die("Not a valid object name %s", argv
[0]);
167 pathspec
= get_pathspec(prefix
, argv
+ 1);
168 tree
= parse_tree_indirect(sha1
);
170 die("not a tree object");
171 read_tree_recursive(tree
, "", 0, 0, pathspec
, show_tree
, NULL
);