builtin-prune-packed.con commit sscanf/strtoul: parse integers robustly (61d6ed1)
   1#include "builtin.h"
   2#include "cache.h"
   3
   4static const char prune_packed_usage[] =
   5"git-prune-packed [-n] [-q]";
   6
   7#define DRY_RUN 01
   8#define VERBOSE 02
   9
  10static void prune_dir(int i, DIR *dir, char *pathname, int len, int opts)
  11{
  12        struct dirent *de;
  13        char hex[40];
  14
  15        sprintf(hex, "%02x", i);
  16        while ((de = readdir(dir)) != NULL) {
  17                unsigned char sha1[20];
  18                if (strlen(de->d_name) != 38)
  19                        continue;
  20                memcpy(hex+2, de->d_name, 38);
  21                if (get_sha1_hex(hex, sha1))
  22                        continue;
  23                if (!has_sha1_pack(sha1, NULL))
  24                        continue;
  25                memcpy(pathname + len, de->d_name, 38);
  26                if (opts & DRY_RUN)
  27                        printf("rm -f %s\n", pathname);
  28                else if (unlink(pathname) < 0)
  29                        error("unable to unlink %s", pathname);
  30        }
  31        pathname[len] = 0;
  32        rmdir(pathname);
  33}
  34
  35void prune_packed_objects(int opts)
  36{
  37        int i;
  38        static char pathname[PATH_MAX];
  39        const char *dir = get_object_directory();
  40        int len = strlen(dir);
  41
  42        if (len > PATH_MAX - 42)
  43                die("impossible object directory");
  44        memcpy(pathname, dir, len);
  45        if (len && pathname[len-1] != '/')
  46                pathname[len++] = '/';
  47        for (i = 0; i < 256; i++) {
  48                DIR *d;
  49
  50                sprintf(pathname + len, "%02x/", i);
  51                d = opendir(pathname);
  52                if (opts == VERBOSE && (d || i == 255))
  53                        fprintf(stderr, "Removing unused objects %d%%...\015",
  54                                ((i+1) * 100) / 256);
  55                if (!d)
  56                        continue;
  57                prune_dir(i, d, pathname, len + 3, opts);
  58                closedir(d);
  59        }
  60        if (opts == VERBOSE)
  61                fprintf(stderr, "\nDone.\n");
  62}
  63
  64int cmd_prune_packed(int argc, const char **argv, const char *prefix)
  65{
  66        int i;
  67        int opts = VERBOSE;
  68
  69        for (i = 1; i < argc; i++) {
  70                const char *arg = argv[i];
  71
  72                if (*arg == '-') {
  73                        if (!strcmp(arg, "-n"))
  74                                opts |= DRY_RUN;
  75                        else if (!strcmp(arg, "-q"))
  76                                opts &= ~VERBOSE;
  77                        else
  78                                usage(prune_packed_usage);
  79                        continue;
  80                }
  81                /* Handle arguments here .. */
  82                usage(prune_packed_usage);
  83        }
  84        sync();
  85        prune_packed_objects(opts);
  86        return 0;
  87}