show-files.con commit [PATCH] Add -z option to show-files (b83c834)
   1/*
   2 * This merges the file listing in the directory cache index
   3 * with the actual working directory list, and shows different
   4 * combinations of the two.
   5 *
   6 * Copyright (C) Linus Torvalds, 2005
   7 */
   8#include <dirent.h>
   9#include <sys/param.h>
  10
  11#include "cache.h"
  12
  13static int show_deleted = 0;
  14static int show_cached = 0;
  15static int show_others = 0;
  16static int show_ignored = 0;
  17static int line_terminator = '\n';
  18
  19static const char **dir;
  20static int nr_dir;
  21static int dir_alloc;
  22
  23static void add_name(const char *pathname, int len)
  24{
  25        char *name;
  26
  27        if (cache_name_pos(pathname, len) >= 0)
  28                return;
  29
  30        if (nr_dir == dir_alloc) {
  31                dir_alloc = alloc_nr(dir_alloc);
  32                dir = realloc(dir, dir_alloc*sizeof(char *));
  33        }
  34        name = malloc(len + 1);
  35        memcpy(name, pathname, len + 1);
  36        dir[nr_dir++] = name;
  37}
  38
  39/*
  40 * Read a directory tree. We currently ignore anything but
  41 * directories and regular files. That's because git doesn't
  42 * handle them at all yet. Maybe that will change some day.
  43 *
  44 * Also, we currently ignore all names starting with a dot.
  45 * That likely will not change.
  46 */
  47static void read_directory(const char *path, const char *base, int baselen)
  48{
  49        DIR *dir = opendir(path);
  50
  51        if (dir) {
  52                struct dirent *de;
  53                char fullname[MAXPATHLEN + 1];
  54                memcpy(fullname, base, baselen);
  55
  56                while ((de = readdir(dir)) != NULL) {
  57                        int len;
  58
  59                        if (de->d_name[0] == '.')
  60                                continue;
  61                        len = strlen(de->d_name);
  62                        memcpy(fullname + baselen, de->d_name, len+1);
  63
  64                        switch (de->d_type) {
  65                        struct stat st;
  66                        default:
  67                                continue;
  68                        case DT_UNKNOWN:
  69                                if (lstat(fullname, &st))
  70                                        continue;
  71                                if (S_ISREG(st.st_mode))
  72                                        break;
  73                                if (!S_ISDIR(st.st_mode))
  74                                        continue;
  75                                /* fallthrough */
  76                        case DT_DIR:
  77                                memcpy(fullname + baselen + len, "/", 2);
  78                                read_directory(fullname, fullname, baselen + len + 1);
  79                                continue;
  80                        case DT_REG:
  81                                break;
  82                        }
  83                        add_name(fullname, baselen + len);
  84                }
  85                closedir(dir);
  86        }
  87}
  88
  89static int cmp_name(const void *p1, const void *p2)
  90{
  91        const char *n1 = *(const char **)p1;
  92        const char *n2 = *(const char **)p2;
  93        int l1 = strlen(n1), l2 = strlen(n2);
  94
  95        return cache_name_compare(n1, l1, n2, l2);
  96}
  97
  98static void show_files(void)
  99{
 100        int i;
 101
 102        /* For cached/deleted files we don't need to even do the readdir */
 103        if (show_others | show_ignored) {
 104                read_directory(".", "", 0);
 105                qsort(dir, nr_dir, sizeof(char *), cmp_name);
 106        }
 107        if (show_others) {
 108                for (i = 0; i < nr_dir; i++)
 109                        printf("%s%c", dir[i], line_terminator);
 110        }
 111        if (show_cached) {
 112                for (i = 0; i < active_nr; i++) {
 113                        struct cache_entry *ce = active_cache[i];
 114                        printf("%s%c", ce->name, line_terminator);
 115                }
 116        }
 117        if (show_deleted) {
 118                for (i = 0; i < active_nr; i++) {
 119                        struct cache_entry *ce = active_cache[i];
 120                        struct stat st;
 121                        if (!stat(ce->name, &st))
 122                                continue;
 123                        printf("%s%c", ce->name, line_terminator);
 124                }
 125        }
 126        if (show_ignored) {
 127                /* We don't have any "ignore" list yet */
 128        }
 129}
 130
 131int main(int argc, char **argv)
 132{
 133        int i;
 134
 135        for (i = 1; i < argc; i++) {
 136                char *arg = argv[i];
 137
 138                if (!strcmp(arg, "-z")) {
 139                        line_terminator = 0;
 140                        continue;
 141                }
 142
 143                if (!strcmp(arg, "--cached")) {
 144                        show_cached = 1;
 145                        continue;
 146                }
 147                if (!strcmp(arg, "--deleted")) {
 148                        show_deleted = 1;
 149                        continue;
 150                }
 151                if (!strcmp(arg, "--others")) {
 152                        show_others = 1;
 153                        continue;
 154                }
 155                if (!strcmp(arg, "--ignored")) {
 156                        show_ignored = 1;
 157                        continue;
 158                }
 159
 160                usage("show-files (--[cached|deleted|others|ignored])*");
 161        }
 162
 163        /* With no flags, we default to showing the cached files */
 164        if (!(show_cached | show_deleted | show_others | show_ignored))
 165                show_cached = 1;
 166
 167        read_cache();
 168        show_files();
 169        return 0;
 170}