git/ls-tree.c
Junio C Hamano 0f2303f719 [PATCH] Un unoptimize ls-tree behaviour
ls-tree unconditionally called read_sha1_file() for all paths
even when not needed, which was a mistake introduced by me.
Rectify this by first checking S_ISDIR(mode) and read the tree
contents only when it is a tree and we are recursive.  There is
no need to read it in any other cases.

The patch also removes the confusing comment that led to this
incorrect implementation.

Thanks to Peter Baudis for noticing this problem.

Signed-off-by: Junio C Hamano <junkio@cox.net>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2005-04-16 13:57:39 -07:00

115 lines
2.3 KiB
C

/*
* GIT - The information manager from hell
*
* Copyright (C) Linus Torvalds, 2005
*/
#include "cache.h"
int line_termination = '\n';
int recursive = 0;
struct path_prefix {
struct path_prefix *prev;
const char *name;
};
static void print_path_prefix(struct path_prefix *prefix)
{
if (prefix) {
if (prefix->prev)
print_path_prefix(prefix->prev);
fputs(prefix->name, stdout);
putchar('/');
}
}
static void list_recursive(void *buffer,
unsigned char *type,
unsigned long size,
struct path_prefix *prefix)
{
struct path_prefix this_prefix;
this_prefix.prev = prefix;
if (strcmp(type, "tree"))
die("expected a 'tree' node");
while (size) {
int namelen = strlen(buffer)+1;
void *eltbuf;
char elttype[20];
unsigned long eltsize;
unsigned char *sha1 = buffer + namelen;
char *path = strchr(buffer, ' ') + 1;
unsigned int mode;
if (size < namelen + 20 || sscanf(buffer, "%o", &mode) != 1)
die("corrupt 'tree' file");
buffer = sha1 + 20;
size -= namelen + 20;
printf("%06o\t%s\t%s\t", mode,
S_ISDIR(mode) ? "tree" : "blob",
sha1_to_hex(sha1));
print_path_prefix(prefix);
fputs(path, stdout);
putchar(line_termination);
if (! recursive || ! S_ISDIR(mode))
continue;
if (! (eltbuf = read_sha1_file(sha1, elttype, &eltsize)) ) {
error("cannot read %s", sha1_to_hex(sha1));
continue;
}
this_prefix.name = path;
list_recursive(eltbuf, elttype, eltsize, &this_prefix);
free(eltbuf);
}
}
static int list(unsigned char *sha1)
{
void *buffer;
unsigned long size;
char type[20];
buffer = read_sha1_file(sha1, type, &size);
if (!buffer)
die("unable to read sha1 file");
list_recursive(buffer, type, size, NULL);
return 0;
}
static const char *ls_tree_usage = "ls-tree [-r] [-z] <key>";
int main(int argc, char **argv)
{
unsigned char sha1[20];
while (1 < argc && argv[1][0] == '-') {
switch (argv[1][1]) {
case 'z':
line_termination = 0;
break;
case 'r':
recursive = 1;
break;
default:
usage(ls_tree_usage);
}
argc--; argv++;
}
if (argc != 2)
usage(ls_tree_usage);
if (get_sha1_hex(argv[1], sha1) < 0)
usage(ls_tree_usage);
sha1_file_directory = getenv(DB_ENVIRONMENT);
if (!sha1_file_directory)
sha1_file_directory = DEFAULT_DB_ENVIRONMENT;
if (list(sha1) < 0)
die("list failed");
return 0;
}