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
, char *pathbuf
)
59 const char *next
, *slash
;
61 struct tree_entry_list
*elem
= &root_entry
, *oldelem
= NULL
;
65 /* Find tree element, descending from root, that
66 * corresponds to the named path, lazily expanding
67 * the tree if possible.
71 /* The fact we still have path means that the caller
72 * wants us to make sure that elem at this point is a
73 * directory, and possibly descend into it. Even what
74 * is left is just trailing slashes, we loop back to
75 * here, and this call to prepare_children() will
76 * catch elem not being a tree. Nice.
78 if (prepare_children(elem
))
81 slash
= strchr(path
, '/');
92 pathbuf
+= sprintf(pathbuf
, "%s/", oldelem
->name
);
95 /* (len == 0) if the original path was "drivers/char/"
96 * and we have run already two rounds, having elem
97 * pointing at the drivers/char directory.
99 elem
= elem
->item
.tree
->entries
;
101 if ((strlen(elem
->name
) == len
) &&
102 !strncmp(elem
->name
, path
, len
)) {
119 static const char *entry_type(struct tree_entry_list
*e
)
121 return (e
->directory
? "tree" : "blob");
124 static const char *entry_hex(struct tree_entry_list
*e
)
126 return sha1_to_hex(e
->directory
127 ? e
->item
.tree
->object
.sha1
128 : e
->item
.blob
->object
.sha1
);
131 /* forward declaration for mutually recursive routines */
132 static int show_entry(struct tree_entry_list
*, int, char *pathbuf
);
134 static int show_children(struct tree_entry_list
*e
, int level
, char *pathbuf
)
136 int oldlen
= strlen(pathbuf
);
138 if (e
!= &root_entry
)
139 sprintf(pathbuf
+ oldlen
, "%s/", e
->name
);
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
, pathbuf
);
149 pathbuf
[oldlen
] = '\0';
154 static int show_entry(struct tree_entry_list
*e
, int level
, char *pathbuf
)
158 if (e
!= &root_entry
) {
159 printf("%06o %s %s %s%s", e
->mode
, entry_type(e
),
160 entry_hex(e
), pathbuf
, e
->name
);
161 putchar(line_termination
);
165 /* If this is a directory, we have the following cases:
166 * (1) This is the top-level request (explicit path from the
167 * command line, or "root" if there is no command line).
168 * a. Without any flag. We show direct children. We do not
170 * b. With -r. We do recurse into children.
171 * c. With -d. We do not recurse into children.
172 * (2) We came here because our caller is either (1-a) or
174 * a. Without any flag. We do not show our children (which
175 * are grandchildren for the original request).
176 * b. With -r. We continue to recurse into our children.
177 * c. With -d. We should not have come here to begin with.
179 if (level
== 0 && !(ls_options
& LS_TREE_ONLY
))
180 /* case (1)-a and (1)-b */
181 err
= err
| show_children(e
, level
+1, pathbuf
);
182 else if (level
&& ls_options
& LS_RECURSIVE
)
184 err
= err
| show_children(e
, level
+1, pathbuf
);
189 static int list_one(const char *path
)
192 char pathbuf
[MAXPATHLEN
+ 1];
193 struct tree_entry_list
*e
= find_entry(path
, pathbuf
);
195 /* traditionally ls-tree does not complain about
196 * missing path. We may change this later to match
197 * what "/bin/ls -a" does, which is to complain.
201 err
= err
| show_entry(e
, 0, pathbuf
);
205 static int list(char **path
)
209 for (i
= 0; path
[i
]; i
++)
210 err
= err
| list_one(path
[i
]);
214 static const char ls_tree_usage
[] =
215 "git-ls-tree [-d] [-r] [-z] <tree-ish> [path...]";
217 int main(int argc
, char **argv
)
219 static char *path0
[] = { "", NULL
};
221 unsigned char sha1
[20];
223 while (1 < argc
&& argv
[1][0] == '-') {
224 switch (argv
[1][1]) {
226 line_termination
= 0;
229 ls_options
|= LS_RECURSIVE
;
232 ls_options
|= LS_TREE_ONLY
;
235 usage(ls_tree_usage
);
241 usage(ls_tree_usage
);
242 if (get_sha1(argv
[1], sha1
) < 0)
243 usage(ls_tree_usage
);
245 path
= (argc
== 2) ? path0
: (argv
+ 2);