a2a5eb0514ad6a0af942f1089f35fe9c45dd82ff
   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
  14#define LS_SHOW_TREES 4
  15static int ls_options = 0;
  16const char **pathspec;
  17
  18static const char ls_tree_usage[] =
  19        "git-ls-tree [-d] [-r] [-t] [-z] <tree-ish> [path...]";
  20
  21static int show_recursive(const char *base, int baselen, const char *pathname)
  22{
  23        const char **s;
  24
  25        if (ls_options & LS_RECURSIVE)
  26                return 1;
  27
  28        s = pathspec;
  29        if (!s)
  30                return 0;
  31
  32        for (;;) {
  33                const char *spec = *s++;
  34                int len, speclen;
  35
  36                if (!spec)
  37                        return 0;
  38                if (strncmp(base, spec, baselen))
  39                        continue;
  40                len = strlen(pathname);
  41                spec += baselen;
  42                speclen = strlen(spec);
  43                if (speclen <= len)
  44                        continue;
  45                if (memcmp(pathname, spec, len))
  46                        continue;
  47                return 1;
  48        }
  49}
  50
  51static int show_tree(unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage)
  52{
  53        int retval = 0;
  54        const char *type = "blob";
  55
  56        if (S_ISDIR(mode)) {
  57                if (show_recursive(base, baselen, pathname)) {
  58                        retval = READ_TREE_RECURSIVE;
  59                        if (!(ls_options & LS_SHOW_TREES))
  60                                return retval;
  61                }
  62                type = "tree";
  63        }
  64
  65        printf("%06o %s %s\t", mode, type, sha1_to_hex(sha1));
  66        write_name_quoted(base, baselen, pathname, line_termination, stdout);
  67        putchar(line_termination);
  68        return retval;
  69}
  70
  71int main(int argc, const char **argv)
  72{
  73        const char *prefix;
  74        unsigned char sha1[20];
  75        char *buf;
  76        unsigned long size;
  77
  78        prefix = setup_git_directory();
  79        while (1 < argc && argv[1][0] == '-') {
  80                switch (argv[1][1]) {
  81                case 'z':
  82                        line_termination = 0;
  83                        break;
  84                case 'r':
  85                        ls_options |= LS_RECURSIVE;
  86                        break;
  87                case 'd':
  88                        ls_options |= LS_TREE_ONLY;
  89                        break;
  90                case 't':
  91                        ls_options |= LS_SHOW_TREES;
  92                        break;
  93                default:
  94                        usage(ls_tree_usage);
  95                }
  96                argc--; argv++;
  97        }
  98
  99        if (argc < 2)
 100                usage(ls_tree_usage);
 101        if (get_sha1(argv[1], sha1) < 0)
 102                usage(ls_tree_usage);
 103
 104        pathspec = get_pathspec(prefix, argv + 2);
 105        buf = read_object_with_reference(sha1, "tree", &size, NULL);
 106        if (!buf)
 107                die("not a tree object");
 108        read_tree_recursive(buf, size, "", 0, 0, pathspec, show_tree);
 109
 110        return 0;
 111}