Compute accurate distances in git-describe before output.
[git] / builtin-prune.c
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
8 static const char prune_usage[] = "git-prune [-n]";
9 static int show_only;
10
11 static 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
29 static 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
72 static 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
82 int 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 }