ls-tree.con commit [PATCH 3/4] split core-git.txt and update (c1bdacf)
   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 unsigned 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        return 0;
  81}
  82
  83static const char *ls_tree_usage = "ls-tree [-r] [-z] <key>";
  84
  85int main(int argc, char **argv)
  86{
  87        unsigned char sha1[20];
  88
  89        while (1 < argc && argv[1][0] == '-') {
  90                switch (argv[1][1]) {
  91                case 'z':
  92                        line_termination = 0;
  93                        break;
  94                case 'r':
  95                        recursive = 1;
  96                        break;
  97                default:
  98                        usage(ls_tree_usage);
  99                }
 100                argc--; argv++;
 101        }
 102
 103        if (argc != 2)
 104                usage(ls_tree_usage);
 105        if (get_sha1(argv[1], sha1) < 0)
 106                usage(ls_tree_usage);
 107        if (list(sha1) < 0)
 108                die("list failed");
 109        return 0;
 110}