/* * GIT - The information manager from hell * * Copyright (C) Linus Torvalds, 2005 */ #include "cache.h" static int line_termination = '\n'; static 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, const 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; buffer = read_object_with_reference(sha1, "tree", &size, NULL); if (!buffer) die("unable to read sha1 file"); list_recursive(buffer, "tree", size, NULL); free(buffer); return 0; } static const char *ls_tree_usage = "git-ls-tree [-r] [-z] "; 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(argv[1], sha1) < 0) usage(ls_tree_usage); if (list(sha1) < 0) die("list failed"); return 0; }