builtin-prune.con commit Make sure git_connect() always give two file descriptors. (ec587fd)
   1#include "cache.h"
   2#include "commit.h"
   3#include "diff.h"
   4#include "revision.h"
   5#include "builtin.h"
   6#include "reachable.h"
   7
   8static const char prune_usage[] = "git-prune [-n]";
   9static int show_only;
  10
  11static int prune_object(char *path, const char *filename, const unsigned char *sha1)
  12{
  13        char buf[20];
  14        const char *type;
  15
  16        if (show_only) {
  17                if (sha1_object_info(sha1, buf, NULL))
  18                        type = "unknown";
  19                else
  20                        type = buf;
  21                printf("%s %s\n", sha1_to_hex(sha1), type);
  22                return 0;
  23        }
  24        unlink(mkpath("%s/%s", path, filename));
  25        rmdir(path);
  26        return 0;
  27}
  28
  29static int prune_dir(int i, char *path)
  30{
  31        DIR *dir = opendir(path);
  32        struct dirent *de;
  33
  34        if (!dir)
  35                return 0;
  36
  37        while ((de = readdir(dir)) != NULL) {
  38                char name[100];
  39                unsigned char sha1[20];
  40                int len = strlen(de->d_name);
  41
  42                switch (len) {
  43                case 2:
  44                        if (de->d_name[1] != '.')
  45                                break;
  46                case 1:
  47                        if (de->d_name[0] != '.')
  48                                break;
  49                        continue;
  50                case 38:
  51                        sprintf(name, "%02x", i);
  52                        memcpy(name+2, de->d_name, len+1);
  53                        if (get_sha1_hex(name, sha1) < 0)
  54                                break;
  55
  56                        /*
  57                         * Do we know about this object?
  58                         * It must have been reachable
  59                         */
  60                        if (lookup_object(sha1))
  61                                continue;
  62
  63                        prune_object(path, de->d_name, sha1);
  64                        continue;
  65                }
  66                fprintf(stderr, "bad sha1 file: %s/%s\n", path, de->d_name);
  67        }
  68        closedir(dir);
  69        return 0;
  70}
  71
  72static void prune_object_dir(const char *path)
  73{
  74        int i;
  75        for (i = 0; i < 256; i++) {
  76                static char dir[4096];
  77                sprintf(dir, "%s/%02x", path, i);
  78                prune_dir(i, dir);
  79        }
  80}
  81
  82int cmd_prune(int argc, const char **argv, const char *prefix)
  83{
  84        int i;
  85        struct rev_info revs;
  86
  87        for (i = 1; i < argc; i++) {
  88                const char *arg = argv[i];
  89                if (!strcmp(arg, "-n")) {
  90                        show_only = 1;
  91                        continue;
  92                }
  93                usage(prune_usage);
  94        }
  95
  96        save_commit_buffer = 0;
  97        init_revisions(&revs, prefix);
  98        mark_reachable_objects(&revs, 1);
  99
 100        prune_object_dir(get_object_directory());
 101
 102        sync();
 103        prune_packed_objects(show_only);
 104        return 0;
 105}