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