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