2 * GIT - The information manager from hell
4 * Copyright (C) Linus Torvalds, 2005
10 static int line_termination
= '\n';
11 #define LS_RECURSIVE 1
12 #define LS_TREE_ONLY 2
13 static int ls_options
= 0;
15 static struct tree_entry_list root_entry
;
17 static void prepare_root(unsigned char *sha1
)
19 unsigned char rsha
[20];
22 struct tree
*root_tree
;
24 buf
= read_object_with_reference(sha1
, "tree", &size
, rsha
);
27 die("Could not read %s", sha1_to_hex(sha1
));
29 root_tree
= lookup_tree(rsha
);
31 die("Could not read %s", sha1_to_hex(sha1
));
33 /* Prepare a fake entry */
34 root_entry
.directory
= 1;
35 root_entry
.executable
= root_entry
.symlink
= 0;
36 root_entry
.mode
= S_IFDIR
;
38 root_entry
.item
.tree
= root_tree
;
39 root_entry
.parent
= NULL
;
42 static int prepare_children(struct tree_entry_list
*elem
)
46 if (!elem
->item
.tree
->object
.parsed
) {
47 struct tree_entry_list
*e
;
48 if (parse_tree(elem
->item
.tree
))
50 /* Set up the parent link */
51 for (e
= elem
->item
.tree
->entries
; e
; e
= e
->next
)
57 static struct tree_entry_list
*find_entry(const char *path
)
59 const char *next
, *slash
;
61 struct tree_entry_list
*elem
= &root_entry
;
63 /* Find tree element, descending from root, that
64 * corresponds to the named path, lazily expanding
65 * the tree if possible.
69 /* The fact we still have path means that the caller
70 * wants us to make sure that elem at this point is a
71 * directory, and possibly descend into it. Even what
72 * is left is just trailing slashes, we loop back to
73 * here, and this call to prepare_children() will
74 * catch elem not being a tree. Nice.
76 if (prepare_children(elem
))
79 slash
= strchr(path
, '/');
89 /* (len == 0) if the original path was "drivers/char/"
90 * and we have run already two rounds, having elem
91 * pointing at the drivers/char directory.
93 elem
= elem
->item
.tree
->entries
;
95 if ((strlen(elem
->name
) == len
) &&
96 !strncmp(elem
->name
, path
, len
)) {
111 static void show_entry_name(struct tree_entry_list
*e
)
113 /* This is yucky. The root level is there for
114 * our convenience but we really want to do a
117 if (e
->parent
&& e
->parent
!= &root_entry
) {
118 show_entry_name(e
->parent
);
121 printf("%s", e
->name
);
124 static const char *entry_type(struct tree_entry_list
*e
)
126 return (e
->directory
? "tree" : "blob");
129 static const char *entry_hex(struct tree_entry_list
*e
)
131 return sha1_to_hex(e
->directory
132 ? e
->item
.tree
->object
.sha1
133 : e
->item
.blob
->object
.sha1
);
136 /* forward declaration for mutually recursive routines */
137 static int show_entry(struct tree_entry_list
*, int);
139 static int show_children(struct tree_entry_list
*e
, int level
)
141 if (prepare_children(e
))
142 die("internal error: ls-tree show_children called with non tree");
143 e
= e
->item
.tree
->entries
;
145 show_entry(e
, level
);
151 static int show_entry(struct tree_entry_list
*e
, int level
)
155 if (e
!= &root_entry
) {
156 printf("%06o %s %s ", e
->mode
, entry_type(e
),
159 putchar(line_termination
);
163 /* If this is a directory, we have the following cases:
164 * (1) This is the top-level request (explicit path from the
165 * command line, or "root" if there is no command line).
166 * a. Without any flag. We show direct children. We do not
168 * b. With -r. We do recurse into children.
169 * c. With -d. We do not recurse into children.
170 * (2) We came here because our caller is either (1-a) or
172 * a. Without any flag. We do not show our children (which
173 * are grandchildren for the original request).
174 * b. With -r. We continue to recurse into our children.
175 * c. With -d. We should not have come here to begin with.
177 if (level
== 0 && !(ls_options
& LS_TREE_ONLY
))
178 /* case (1)-a and (1)-b */
179 err
= err
| show_children(e
, level
+1);
180 else if (level
&& ls_options
& LS_RECURSIVE
)
182 err
= err
| show_children(e
, level
+1);
187 static int list_one(const char *path
)
190 struct tree_entry_list
*e
= find_entry(path
);
192 /* traditionally ls-tree does not complain about
193 * missing path. We may change this later to match
194 * what "/bin/ls -a" does, which is to complain.
198 err
= err
| show_entry(e
, 0);
202 static int list(char **path
)
206 for (i
= 0; path
[i
]; i
++)
207 err
= err
| list_one(path
[i
]);
211 static const char *ls_tree_usage
=
212 "git-ls-tree [-d] [-r] [-z] <tree-ish> [path...]";
214 int main(int argc
, char **argv
)
216 static char *path0
[] = { "", NULL
};
218 unsigned char sha1
[20];
220 while (1 < argc
&& argv
[1][0] == '-') {
221 switch (argv
[1][1]) {
223 line_termination
= 0;
226 ls_options
|= LS_RECURSIVE
;
229 ls_options
|= LS_TREE_ONLY
;
232 usage(ls_tree_usage
);
238 usage(ls_tree_usage
);
239 if (get_sha1(argv
[1], sha1
) < 0)
240 usage(ls_tree_usage
);
242 path
= (argc
== 2) ? path0
: (argv
+ 2);