builtin-prune.con commit Merge GIT 1.5.0.4 (803527f)
   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                return 0;
  18        }
  19        unlink(mkpath("%s/%s", path, filename));
  20        rmdir(path);
  21        return 0;
  22}
  23
  24static int prune_dir(int i, char *path)
  25{
  26        DIR *dir = opendir(path);
  27        struct dirent *de;
  28
  29        if (!dir)
  30                return 0;
  31
  32        while ((de = readdir(dir)) != NULL) {
  33                char name[100];
  34                unsigned char sha1[20];
  35                int len = strlen(de->d_name);
  36
  37                switch (len) {
  38                case 2:
  39                        if (de->d_name[1] != '.')
  40                                break;
  41                case 1:
  42                        if (de->d_name[0] != '.')
  43                                break;
  44                        continue;
  45                case 38:
  46                        sprintf(name, "%02x", i);
  47                        memcpy(name+2, de->d_name, len+1);
  48                        if (get_sha1_hex(name, sha1) < 0)
  49                                break;
  50
  51                        /*
  52                         * Do we know about this object?
  53                         * It must have been reachable
  54                         */
  55                        if (lookup_object(sha1))
  56                                continue;
  57
  58                        prune_object(path, de->d_name, sha1);
  59                        continue;
  60                }
  61                fprintf(stderr, "bad sha1 file: %s/%s\n", path, de->d_name);
  62        }
  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}