summaryrefslogtreecommitdiff
path: root/ls-tree.c
diff options
context:
space:
mode:
authorJunio C Hamano <junkio@cox.net>2005-05-31 18:46:47 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-05-31 20:32:27 -0700
commit66204988fe2e5a2a18c4ff55798c7203775d9fd4 (patch)
treeb44e2c7309c5a90d34b61eb2b19499aebce07f6d /ls-tree.c
parent8c7fa2478e16227c8f42d05758bf669b144c5055 (diff)
downloadgit-66204988fe2e5a2a18c4ff55798c7203775d9fd4.tar.gz
[PATCH] ls-tree: handle trailing slashes in the pathspec properly.
This fixes the problem with ls-tree which failed to show "drivers/char" directory when the user asked for "drivers/char/" from the command line. At the same time, if "drivers/char" were a non directory, "drivers/char/" would not show it. This is consistent with the way diffcore-pathspec has been recently fixed. This adds back the diffcore-pathspec test,dropped when my earlier diffcore-pathspec fix was rejected. Signed-off-by: Junio C Hamano <junkio@cox.net> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'ls-tree.c')
-rw-r--r--ls-tree.c94
1 files changed, 47 insertions, 47 deletions
diff --git a/ls-tree.c b/ls-tree.c
index d2a57d0b47..450bff2472 100644
--- a/ls-tree.c
+++ b/ls-tree.c
@@ -54,54 +54,58 @@ static int prepare_children(struct tree_entry_list *elem)
return 0;
}
-static struct tree_entry_list *find_entry_0(struct tree_entry_list *elem,
- const char *path,
- const char *path_end)
+static struct tree_entry_list *find_entry(const char *path)
{
- const char *ep;
+ const char *next, *slash;
int len;
+ struct tree_entry_list *elem = &root_entry;
- while (path < path_end) {
+ /* Find tree element, descending from root, that
+ * corresponds to the named path, lazily expanding
+ * the tree if possible.
+ */
+
+ while (path) {
+ /* The fact we still have path means that the caller
+ * wants us to make sure that elem at this point is a
+ * directory, and possibly descend into it. Even what
+ * is left is just trailing slashes, we loop back to
+ * here, and this call to prepare_children() will
+ * catch elem not being a tree. Nice.
+ */
if (prepare_children(elem))
return NULL;
- /* In elem->tree->entries, find the one that has name
- * that matches what is between path and ep.
- */
- elem = elem->item.tree->entries;
-
- ep = strchr(path, '/');
- if (!ep || path_end <= ep)
- ep = path_end;
- len = ep - path;
-
- while (elem) {
- if ((strlen(elem->name) == len) &&
- !strncmp(elem->name, path, len))
- break;
- elem = elem->next;
+ slash = strchr(path, '/');
+ if (!slash) {
+ len = strlen(path);
+ next = 0;
+ }
+ else {
+ next = slash + 1;
+ len = slash - path;
+ }
+ if (len) {
+ /* (len == 0) if the original path was "drivers/char/"
+ * and we have run already two rounds, having elem
+ * pointing at the drivers/char directory.
+ */
+ elem = elem->item.tree->entries;
+ while (elem) {
+ if ((strlen(elem->name) == len) &&
+ !strncmp(elem->name, path, len)) {
+ /* found */
+ break;
+ }
+ elem = elem->next;
+ }
+ if (!elem)
+ return NULL;
}
- if (path_end <= ep || !elem)
- return elem;
- while (*ep == '/' && ep < path_end)
- ep++;
- path = ep;
+ path = next;
}
- return NULL;
-}
-static struct tree_entry_list *find_entry(const char *path,
- const char *path_end)
-{
- /* Find tree element, descending from root, that
- * corresponds to the named path, lazily expanding
- * the tree if possible.
- */
- if (path == path_end) {
- /* Special. This is the root level */
- return &root_entry;
- }
- return find_entry_0(&root_entry, path, path_end);
+ return elem;
}
static void show_entry_name(struct tree_entry_list *e)
@@ -180,10 +184,10 @@ static int show_entry(struct tree_entry_list *e, int level)
return err;
}
-static int list_one(const char *path, const char *path_end)
+static int list_one(const char *path)
{
int err = 0;
- struct tree_entry_list *e = find_entry(path, path_end);
+ struct tree_entry_list *e = find_entry(path);
if (!e) {
/* traditionally ls-tree does not complain about
* missing path. We may change this later to match
@@ -199,12 +203,8 @@ static int list(char **path)
{
int i;
int err = 0;
- for (i = 0; path[i]; i++) {
- int len = strlen(path[i]);
- while (0 <= len && path[i][len] == '/')
- len--;
- err = err | list_one(path[i], path[i] + len);
- }
+ for (i = 0; path[i]; i++)
+ err = err | list_one(path[i]);
return err;
}