4df58301261b67f511c0855ab7e06c91e158fc43
   1/*
   2 * GIT - The information manager from hell
   3 *
   4 * Copyright (C) Linus Torvalds, 2005
   5 */
   6#include "cache.h"
   7#include "blob.h"
   8#include "tree.h"
   9#include "quote.h"
  10
  11static int line_termination = '\n';
  12#define LS_RECURSIVE 1
  13#define LS_TREE_ONLY 2
  14static int ls_options = 0;
  15const char **pathspec;
  16
  17static const char ls_tree_usage[] =
  18        "git-ls-tree [-d] [-r] [-z] <tree-ish> [path...]";
  19
  20static int show_tree(unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage)
  21{
  22        const char *type = "blob";
  23
  24        if (S_ISDIR(mode)) {
  25                const char **s;
  26                if (ls_options & LS_RECURSIVE)
  27                        return READ_TREE_RECURSIVE;
  28                s = pathspec;
  29                if (s) {
  30                        for (;;) {
  31                                const char *spec = *s++;
  32                                int len, speclen;
  33
  34                                if (!spec)
  35                                        break;
  36                                if (strncmp(base, spec, baselen))
  37                                        continue;
  38                                len = strlen(pathname);
  39                                spec += baselen;
  40                                speclen = strlen(spec);
  41                                if (speclen <= len)
  42                                        continue;
  43                                if (memcmp(pathname, spec, len))
  44                                        continue;
  45                                return READ_TREE_RECURSIVE;
  46                        }
  47                }
  48                type = "tree";
  49        }
  50
  51        printf("%06o %s %s\t%.*s%s%c", mode, type, sha1_to_hex(sha1), baselen, base, pathname, line_termination);
  52        return 0;
  53}
  54
  55int main(int argc, const char **argv)
  56{
  57        const char *prefix;
  58        unsigned char sha1[20];
  59        char *buf;
  60        unsigned long size;
  61
  62        prefix = setup_git_directory();
  63        while (1 < argc && argv[1][0] == '-') {
  64                switch (argv[1][1]) {
  65                case 'z':
  66                        line_termination = 0;
  67                        break;
  68                case 'r':
  69                        ls_options |= LS_RECURSIVE;
  70                        break;
  71                case 'd':
  72                        ls_options |= LS_TREE_ONLY;
  73                        break;
  74                default:
  75                        usage(ls_tree_usage);
  76                }
  77                argc--; argv++;
  78        }
  79
  80        if (argc < 2)
  81                usage(ls_tree_usage);
  82        if (get_sha1(argv[1], sha1) < 0)
  83                usage(ls_tree_usage);
  84
  85        pathspec = get_pathspec(prefix, argv + 2);
  86        buf = read_object_with_reference(sha1, "tree", &size, NULL);
  87        if (!buf)
  88                die("not a tree object");
  89        read_tree_recursive(buf, size, "", 0, 0, pathspec, show_tree);
  90
  91        return 0;
  92}