ls-tree.con commit [PATCH] Document -R option for git-diff-tree. (e593638)
   1/*
   2 * GIT - The information manager from hell
   3 *
   4 * Copyright (C) Linus Torvalds, 2005
   5 */
   6#include "cache.h"
   7
   8int line_termination = '\n';
   9int recursive = 0;
  10
  11struct path_prefix {
  12        struct path_prefix *prev;
  13        const char *name;
  14};
  15
  16static void print_path_prefix(struct path_prefix *prefix)
  17{
  18        if (prefix) {
  19                if (prefix->prev)
  20                        print_path_prefix(prefix->prev);
  21                fputs(prefix->name, stdout);
  22                putchar('/');
  23        }
  24}
  25
  26static void list_recursive(void *buffer,
  27                           const char *type,
  28                           unsigned long size,
  29                           struct path_prefix *prefix)
  30{
  31        struct path_prefix this_prefix;
  32        this_prefix.prev = prefix;
  33
  34        if (strcmp(type, "tree"))
  35                die("expected a 'tree' node");
  36
  37        while (size) {
  38                int namelen = strlen(buffer)+1;
  39                void *eltbuf;
  40                char elttype[20];
  41                unsigned long eltsize;
  42                unsigned char *sha1 = buffer + namelen;
  43                char *path = strchr(buffer, ' ') + 1;
  44                unsigned int mode;
  45
  46                if (size < namelen + 20 || sscanf(buffer, "%o", &mode) != 1)
  47                        die("corrupt 'tree' file");
  48                buffer = sha1 + 20;
  49                size -= namelen + 20;
  50
  51                printf("%06o\t%s\t%s\t", mode,
  52                       S_ISDIR(mode) ? "tree" : "blob",
  53                       sha1_to_hex(sha1));
  54                print_path_prefix(prefix);
  55                fputs(path, stdout);
  56                putchar(line_termination);
  57
  58                if (! recursive || ! S_ISDIR(mode))
  59                        continue;
  60
  61                if (! (eltbuf = read_sha1_file(sha1, elttype, &eltsize)) ) {
  62                        error("cannot read %s", sha1_to_hex(sha1));
  63                        continue;
  64                }
  65                this_prefix.name = path;
  66                list_recursive(eltbuf, elttype, eltsize, &this_prefix);
  67                free(eltbuf);
  68        }
  69}
  70
  71static int list(unsigned char *sha1)
  72{
  73        void *buffer;
  74        unsigned long size;
  75
  76        buffer = read_object_with_reference(sha1, "tree", &size, 0);
  77        if (!buffer)
  78                die("unable to read sha1 file");
  79        list_recursive(buffer, "tree", size, NULL);
  80        free(buffer);
  81        return 0;
  82}
  83
  84static const char *ls_tree_usage = "git-ls-tree [-r] [-z] <key>";
  85
  86int main(int argc, char **argv)
  87{
  88        unsigned char sha1[20];
  89
  90        while (1 < argc && argv[1][0] == '-') {
  91                switch (argv[1][1]) {
  92                case 'z':
  93                        line_termination = 0;
  94                        break;
  95                case 'r':
  96                        recursive = 1;
  97                        break;
  98                default:
  99                        usage(ls_tree_usage);
 100                }
 101                argc--; argv++;
 102        }
 103
 104        if (argc != 2)
 105                usage(ls_tree_usage);
 106        if (get_sha1(argv[1], sha1) < 0)
 107                usage(ls_tree_usage);
 108        if (list(sha1) < 0)
 109                die("list failed");
 110        return 0;
 111}